Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>toFormatter(this, colorize);
}
/**
* Initialize the compiler options. Only necessary if you're not doing
* a normal compile() job.
*/
public void initOptions(CompilerOptions options) {
this.options = options;
if (errorManager == null) {
if (outStream == null) {
setErrorManager(
new LoggerErrorManager(createMessageFormatter(), logger));
} else {
PrintStreamErrorManager printer =
new PrintStreamErrorManager(createMessageFormatter(), outStream);
printer.setSummaryDetailLevel(options.summaryDetailLevel);
setErrorManager(printer);
}
}
}
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSSourceFile[] inputs,
CompilerOptions options) {
initOptions(options);
}
this.inputs = getAllInputsFromModules();
initBasedOnOptions();
initInputsByNameMap();
}
/**
* Do any initialization that is dependent on the compiler options.
*/
private void initBasedOnOptions() {
// Create the source map if necessary.
if (options.sourceMapOutputPath != null) {
sourceMap = new SourceMap();
}
}
private CompilerInput[] makeCompilerInput(
JSSourceFile[] files, boolean isExtern) {
CompilerInput [] inputs = new CompilerInput[files.length];
for (int i = 0; i < files.length; ++i) {
inputs[i] = new CompilerInput(files[i], isExtern);
}
return inputs;
}
private static final DiagnosticType EMPTY_MODULE_LIST_ERROR =
DiagnosticType.error("JSC_EMPTY_MODULE_LIST_ERROR",
"At least one module must be provided");
private static final DiagnosticType EMPTY_ROOT_MODULE_ERROR =
}
/**
* Builds a single list of all module inputs. Verifies that it contains no
* duplicates.
*/
private CompilerInput[] getAllInputsFromModules() {
List<CompilerInput> inputs = new ArrayList<CompilerInput>();
Map<String, JSModule> inputMap = new HashMap<String, JSModule>();
for (JSModule module : modules) {
for (CompilerInput input : module.getInputs()) {
String inputName = input
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>.getName();
JSModule firstModule = inputMap.get(inputName);
if (firstModule == null) {
inputs.add(input);
inputMap.put(inputName, module);
} else {
report(JSError.make(DUPLICATE_INPUT_IN_MODULES,
firstModule.getName(), module.getName(), inputName));
}
}
}
if (hasErrors()) {
// There's no reason to bother parsing the code.
return new CompilerInput[0];
}
return inputs.toArray(new CompilerInput[inputs.size()]);
}
static final DiagnosticType DUPLICATE_INPUT =
DiagnosticType.error("JSC_DUPLICATE_INPUT", "Duplicate input: {0}");
static final DiagnosticType DUPLICATE_EXTERN_INPUT =
DiagnosticType.error("JSC_DUPLICATE_EXTERN_INPUT",
"Duplicate extern input: {0}");
/**
* Creates a map to make looking up an input by name fast. Also checks for
* duplicate inputs.
*/
void initInputsByNameMap() {
inputsByName = new HashMap<String, CompilerInput>();
for (CompilerInput input : externs) {
String name = input.getName();
if (!inputsByName.containsKey(name)) {
inputsByName.put(name, input);
} else {
report(JSError.make(DUPLICATE_EXTERN_INPUT, name));
}
}
for (CompilerInput input : inputs) {
String name = input.getName();
if (!inputsByName.containsKey(name)) {
inputsByName.put(name, input);
} else {
report(JSError.make(DUPLICATE_INPUT, name));
}
}
}
public Result compile(
JSSourceFile extern, JSSourceFile input, CompilerOptions options) {
return compile(extern, new JSSourceFile[] { input }, options);
}
public Result compile(
JSSourceFile extern, JSSourceFile[] input, CompilerOptions options) {
return compile(new JSSourceFile[] { extern }, input, options);
}
public Result compile(
JSSourceFile extern, JSModule[] modules, CompilerOptions options) {
return compile(new JSSourceFile[] { extern }, modules, options);
}
/**
* Compiles
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>("parseInputs");
try {
// Parse externs sources.
externsRoot = new Node(Token.BLOCK);
externsRoot.setIsSyntheticBlock(true);
for (CompilerInput input : externs) {
Node n = input.getAstRoot(this);
if (hasErrors()) {
return null;
}
externsRoot.addChildToBack(n);
}
for (CompilerInput input : inputs) {
Node n = input.getAstRoot(this);
if (hasErrors()) {
return null;
}
// Inputs can have a null AST during initial parse.
if (n == null) {
continue;
}
if (devMode) {
runSanityCheck();
if (hasErrors()) {
return null;
}
}
if (options.sourceMapOutputPath != null ||
options.nameReferenceReportPath != null) {
// Annotate the nodes in the tree with information from the
// input file. This information is used to construct the SourceMap.
SourceInformationAnnotator sia =
new SourceInformationAnnotator(input.getName());
NodeTraversal.traverse(this, n, sia);
}
jsRoot.addChildToBack(n);
}
externAndJsRoot = new Node(Token.BLOCK, externsRoot, jsRoot);
externAndJsRoot.setIsSyntheticBlock(true);
return externAndJsRoot;
} finally {
stopTracer(tracer, "parseInputs");
}
}
public Node parse(JSSourceFile file) {
initCompilerOptionsIfTesting();
addToDebugLog("Parsing: " + file.getName());
return new JsAst(file).getAstRoot(this);
}
@Override
Node parseSyntheticCode(String js) {
CompilerInput input = new CompilerInput(
JSSourceFile.fromCode(" [synthetic] ", js));
inputsByName.put(input.getName(), input);
return input.getAstRoot(this);
}
void initCompilerOptionsIfTesting() {
if (options == null) {
// initialization for tests that don't initialize the compiler
// by the normal mechanisms.
initOptions(new CompilerOptions());
}
}
@Override
Node parseSyntheticCode(String fileName, String js) {
initCompilerOptions
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>IfTesting();
return parse(JSSourceFile.fromCode(fileName, js));
}
Node parseTestCode(String js) {
initCompilerOptionsIfTesting();
CompilerInput input = new CompilerInput(
JSSourceFile.fromCode(" [testcode] ", js));
if (inputsByName == null) {
inputsByName = Maps.newHashMap();
}
inputsByName.put(input.getName(), input);
return input.getAstRoot(this);
}
@Override
ErrorReporter getDefaultErrorReporter() {
return defaultErrorReporter;
}
//------------------------------------------------------------------------
// Convert back to source code
//------------------------------------------------------------------------
/**
* Converts the main parse tree back to js code.
*/
public String toSource() {
return runInCompilerThread(new Callable<String>() {
public String call() throws Exception {
Tracer tracer = newTracer("toSource");
try {
CodeBuilder cb = new CodeBuilder();
if (jsRoot != null) {
int i = 0;
for (Node scriptNode = jsRoot.getFirstChild();
scriptNode != null;
scriptNode = scriptNode.getNext()) {
toSource(cb, i++, scriptNode);
}
}
return cb.toString();
} finally {
stopTracer(tracer, "toSource");
}
}
});
}
/**
* Converts the parse tree for each input back to js code.
*/
public String[] toSourceArray() {
return runInCompilerThread(new Callable<String[]>() {
public String[] call() throws Exception {
Tracer tracer = newTracer("toSourceArray");
try {
int numInputs = inputs.length;
String[] sources = new String[numInputs];
CodeBuilder cb = new CodeBuilder();
for (int i = 0; i < numInputs; i++) {
Node scriptNode = inputs[i].getAstRoot(Compiler.this);
cb.reset();
toSource(cb, i, scriptNode);
sources[i] = cb.toString();
}
return sources;
} finally {
stopTracer(tracer, "toSourceArray");
}
}
});
}
/**
* Converts the parse tree for a module back to js code.
*/
public String toSource(final JSModule module) {
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
return runInCompilerThread(new Callable<String>() {
public String call() throws Exception {
List<CompilerInput> inputs = module.getInputs();
int numInputs = inputs.size();
if (numInputs == 0) {
return "";
}
CodeBuilder cb = new CodeBuilder();
for (int i = 0; i < numInputs; i++) {
Node scriptNode = inputs.get(i).getAstRoot(Compiler.this);
if (scriptNode == null) {
throw new IllegalArgumentException(
"Bad module: " + module.getName());
}
toSource(cb, i, scriptNode);
}
return cb.toString();
}
});
}
/**
* Converts the parse tree for each input in a module back to js code.
*/
public String[] toSourceArray(final JSModule module) {
return runInCompilerThread(new Callable<String[]>() {
public String[] call() throws Exception {
List<CompilerInput> inputs = module.getInputs();
int numInputs = inputs.size();
if (numInputs == 0) {
return new String[0];
}
String[] sources = new String[numInputs];
CodeBuilder cb = new CodeBuilder();
for (int i = 0; i < numInputs; i++) {
Node scriptNode = inputs.get(i).getAstRoot(Compiler.this);
if (scriptNode == null) {
throw new IllegalArgumentException(
"Bad module input: " + inputs.get(i).getName());
}
cb.reset();
toSource(cb, i, scriptNode);
sources[i] = cb.toString();
}
return sources;
}
});
}
/**
* Writes out js code from a root node. If printing input delimiters, this
* method will attach a comment to the start of the text indicating which
* input the output derived from. If there were any preserve annotations
* within the root's source, they will also be printed in a block comment
* at the beginning of the output.
*/
public void toSource(final CodeBuilder cb,
final int inputSeqNum,
final Node root) {
runInCompilerThread(new Callable<Void>() {
public Void call() throws Exception {
if (options.printInputDelimiter
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
* For each target, we apply the target-specific defines by calling
* {@code processDefines} and then {@code optimize} to optimize the AST
* specifically for that target.
*/
public void processDefines() {
(new DefaultPassConfig(options)).processDefines.create(this)
.process(externsRoot, jsRoot);
}
boolean isInliningForbidden() {
return options.propertyRenaming == PropertyRenamingPolicy.HEURISTIC ||
options.propertyRenaming ==
PropertyRenamingPolicy.AGGRESSIVE_HEURISTIC;
}
/** Control Flow Analysis. */
ControlFlowGraph<Node> computeCFG() {
logger.info("Computing Control Flow Graph");
Tracer tracer = newTracer("computeCFG");
ControlFlowAnalysis cfa = new ControlFlowAnalysis(this, true);
process(cfa);
stopTracer(tracer, "computeCFG");
return cfa.getCfg();
}
public void normalize() {
logger.info("Normalizing");
startPass("normalize");
process(new Normalize(this, false));
setNormalized();
endPass();
}
@Override
void prepareAst(Node root) {
Tracer tracer = newTracer("prepareAst");
CompilerPass pass = new PrepareAst(this);
pass.process(null, root);
stopTracer(tracer, "prepareAst");
}
void recordFunctionInformation() {
logger.info("Recording function information");
startPass("recordFunctionInformation");
RecordFunctionInformation recordFunctionInfoPass =
new RecordFunctionInformation(
this, getPassConfig().getIntermediateState().functionNames);
process(recordFunctionInfoPass);
functionInformationMap = recordFunctionInfoPass.getMap();
endPass();
}
protected final CodeChangeHandler.RecentChange recentChange =
new CodeChangeHandler.RecentChange();
private final List<CodeChangeHandler> codeChangeHandlers =
Lists.<CodeChangeHandler>newArrayList();
@Override
void addChangeHandler(CodeChangeHandler handler) {
codeChangeHandlers.add(handler);
}
@Override
void removeChangeHandler(CodeChangeHandler handler) {
codeChangeHandlers.remove(handler);
}
/**
* All passes should call reportCodeChange() when they alter
* the JS tree structure. This is verified by CompilerTestCase.
* This allows us to
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> int end = pos;
int endLine = startLine;
for (int n = 0; n < SOURCE_EXCERPT_REGION_LENGTH; n++, endLine++) {
end = js.indexOf('\n', end);
if (end == -1) {
break;
}
end++;
}
if (lineNumber >= endLine) {
return null;
}
if (end == -1) {
int last = js.length() - 1;
if (js.charAt(last) == '\n') {
return
new SimpleRegion(startLine, endLine, js.substring(pos, last));
} else {
return new SimpleRegion(startLine, endLine, js.substring(pos));
}
} else {
return new SimpleRegion(startLine, endLine, js.substring(pos, end));
}
}
public static SourceFile fromFile(String fileName, Charset c) {
return fromFile(new File(fileName), c);
}
public static SourceFile fromFile(String fileName) {
return fromFile(new File(fileName));
}
public static SourceFile fromFile(File file, Charset c) {
return new OnDisk(file, c);
}
public static SourceFile fromFile(File file) {
return new OnDisk(file);
}
public static SourceFile fromCode(String fileName, String code) {
return new Preloaded(fileName, code);
}
public static SourceFile fromCode(String fileName,
String originalPath, String code) {
return new Preloaded(fileName, originalPath, code);
}
public static SourceFile fromInputStream(String fileName, InputStream s)
throws IOException {
return fromCode(fileName,
CharStreams.toString(new InputStreamReader(s, Charsets.UTF_8)));
}
public static SourceFile fromInputStream(String fileName,
String originalPath, InputStream s) throws IOException {
return fromCode(fileName, originalPath,
CharStreams.toString(new InputStreamReader(s, Charsets.UTF_8)));
}
public static SourceFile fromReader(String fileName, Reader r)
throws IOException {
return fromCode(fileName, CharStreams.toString(r));
}
public static SourceFile fromGenerator(String fileName,
Generator generator) {
return new Generated
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>(String sourceName) {
this.sourceName = sourceName;
}
public final int getEncodedSourceStart() { return encodedSourceStart; }
public final int getEncodedSourceEnd() { return encodedSourceEnd; }
public final void setEncodedSourceBounds(int start, int end) {
this.encodedSourceStart = start;
this.encodedSourceEnd = end;
}
public final int getBaseLineno() { return baseLineno; }
public final void setBaseLineno(int lineno) {
// One time action
if (lineno < 0 || baseLineno >= 0) Kit.codeBug();
baseLineno = lineno;
}
public final int getEndLineno() { return endLineno; }
public final void setEndLineno(int lineno) {
// One time action
if (lineno < 0 || endLineno >= 0) Kit.codeBug();
endLineno = lineno;
}
public final int getFunctionCount() {
if (functions == null) { return 0; }
return functions.size();
}
public final FunctionNode getFunctionNode(int i) {
return (FunctionNode)functions.get(i);
}
public final int addFunction(FunctionNode fnNode) {
if (fnNode == null) Kit.codeBug();
if (functions == null) { functions = new ObjArray(); }
functions.add(fnNode);
return functions.size() - 1;
}
public final int getRegexpCount() {
if (regexps == null) { return 0; }
return regexps.size() / 2;
}
public final String getRegexpString(int index) {
return (String)regexps.get(index * 2);
}
public final String getRegexpFlags(int index) {
return (String)regexps.get(index * 2 + 1);
}
public final int addRegexp(String string, String flags) {
if (string == null) Kit.codeBug();
if (regexps == null) { regexps = new ObjArray(); }
regexps.add(string);
regexps.add(flags);
return regexps.size() / 2 - 1;
}
public final boolean hasParamOrVar
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>(String name) {
return itsVariableNames.has(name);
}
public final int getParamOrVarIndex(String name) {
return itsVariableNames.get(name, -1);
}
public final String getParamOrVarName(int index) {
return (String)itsVariables.get(index);
}
public final int getParamCount() {
return varStart;
}
public final int getParamAndVarCount() {
return itsVariables.size();
}
public final String[] getParamAndVarNames() {
int N = itsVariables.size();
if (N == 0) {
return ScriptRuntime.emptyStrings;
}
String[] array = new String[N];
itsVariables.toArray(array);
return array;
}
public final boolean[] getParamAndVarConst() {
int N = itsVariables.size();
boolean[] array = new boolean[N];
for (int i = 0; i < N; i++)
if (itsConst.get(i) != null)
array[i] = true;
return array;
}
public final void addParam(String name) {
// Check addparam is not called after addLocal
if (varStart != itsVariables.size()) Kit.codeBug();
// Allow non-unique parameter names: use the last occurrence (parser
// will warn about dups)
int index = varStart++;
itsVariables.add(name);
itsConst.add(null);
itsVariableNames.put(name, index);
}
public static final int NO_DUPLICATE = 1;
public static final int DUPLICATE_VAR = 0;
public static final int DUPLICATE_PARAMETER = -1;
public static final int DUPLICATE_CONST = -2;
/**
* This function adds a variable to the set of var declarations for a
* function (or script). This returns an indicator of a duplicate that
* overrides a formal parameter (false if this dups a parameter).
* @param name variable name
* @return 1 if the name is not any form of duplicate, 0 if it duplicates a
* non-parameter, -1 if it duplicates a parameter and -2 if it duplicates a
* const.
*/
public final int
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> addVar(String name) {
int vIndex = itsVariableNames.get(name, -1);
if (vIndex != -1) {
// There's already a variable or parameter with this name.
if (vIndex >= varStart) {
Object v = itsConst.get(vIndex);
if (v != null)
return DUPLICATE_CONST;
else
return DUPLICATE_VAR;
} else
return DUPLICATE_PARAMETER;
}
int index = itsVariables.size();
itsVariables.add(name);
itsConst.add(null);
itsVariableNames.put(name, index);
return NO_DUPLICATE;
}
public final boolean addConst(String name) {
int vIndex = itsVariableNames.get(name, -1);
if (vIndex != -1) {
// There's already a variable or parameter with this name.
return false;
}
int index = itsVariables.size();
itsVariables.add(name);
itsConst.add(name);
itsVariableNames.put(name, index);
return true;
}
public final void removeParamOrVar(String name) {
int i = itsVariableNames.get(name, -1);
if (i != -1) {
itsVariables.remove(i);
itsVariableNames.remove(name);
ObjToIntMap.Iterator iter = itsVariableNames.newIterator();
for (iter.start(); !iter.done(); iter.next()) {
int v = iter.getValue();
if (v > i) {
iter.setValue(v - 1);
}
}
}
}
public final Object getCompilerData()
{
return compilerData;
}
public final void setCompilerData(Object data)
{
if (data == null) throw new IllegalArgumentException();
// Can only call once
if (compilerData != null) throw new IllegalStateException();
compilerData = data;
}
private int encodedSourceStart;
private int encodedSourceEnd;
private String sourceName;
private int baseLineno = -1;
private int endLineno = -1;
private ObjArray functions;
private ObjArray regexps;
// a list of the formal parameters and local variables
private ObjArray itsVariables
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> is relative only to the current
* run of the CodeConsumer and will be normalized
* later on by the SourceMap.
*
* @see SourceMap
*/
private static class Mapping {
Node node;
Position start;
Position end;
}
/**
* Starts the source mapping for the given
* node at the current position.
*/
@Override
void startSourceMapping(Node node) {
if (createSrcMap
&& node.getProp(Node.SOURCEFILE_PROP) != null
&& node.getLineno() > 0) {
int line = getCurrentLineIndex();
int index = getCurrentCharIndex();
// If the index is -1, we are not performing any mapping.
if (index >= 0) {
Mapping mapping = new Mapping();
mapping.node = node;
mapping.start = new Position(line, index);
mappings.push(mapping);
allMappings.add(mapping);
}
}
}
/**
* Finishes the source mapping for the given
* node at the current position.
*/
@Override
void endSourceMapping(Node node) {
if (createSrcMap
&& node.getProp(Node.SOURCEFILE_PROP) != null
&& node.getLineno() > 0) {
int line = getCurrentLineIndex();
int index = getCurrentCharIndex();
// If the index is -1, we are not performing any mapping.
if (index >= 0) {
Preconditions.checkState(
!mappings.empty(), "Mismatch in start and end of mapping");
Mapping mapping = mappings.pop();
mapping.end = new Position(line, index);
}
}
}
/**
* Generates the source map from the given code consumer,
* appending the information it saved to the SourceMap
* object given.
*/
@Override
void generateSourceMap(SourceMap map){
if (createSrcMap) {
for (Mapping mapping : allMappings) {
map.addMapping(mapping.node, mapping.start, mapping.end);
}
}
}
/**
* Reports to the code consumer that the given line has been cut at the
* given position (i.e. a \n has been inserted there). All mappings in
* the source maps after that position will be renormalized
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>Threshold;
}
public String getCode() {
return code.toString();
}
@Override
char getLastChar() {
return (code.length() > 0) ? code.charAt(code.length() - 1) : '\0';
}
@Override
int getCurrentBufferLength() {
return code.length();
}
@Override
int getCurrentCharIndex() {
return lineLength;
}
@Override
int getCurrentLineIndex() {
return lineIndex;
}
/**
* Appends a string to the code, keeping track of the current line length.
*/
@Override
void append(String str) {
// For pretty printing: indent at the beginning of the line
if (lineLength == 0) {
for (int i = 0; i < indent; i++) {
code.append(INDENT);
lineLength += INDENT.length();
}
}
code.append(str);
lineLength += str.length();
}
/**
* Adds a newline to the code, resetting the line length and handling
* indenting for pretty printing.
*/
@Override
void startNewLine() {
if (lineLength > 0) {
code.append('\n');
lineIndex++;
lineLength = 0;
}
}
@Override
void maybeLineBreak() {
maybeCutLine();
}
/**
* This may start a new line if the current line is longer than the line
* length threshold.
*/
@Override
void maybeCutLine() {
if (lineLength > lineLengthThreshold) {
startNewLine();
}
}
@Override
void endLine() {
startNewLine();
}
@Override
void appendBlockStart() {
append(" {");
indent++;
}
@Override
void appendBlockEnd() {
endLine();
indent--;
append("}");
}
@Override
void listSeparator() {
add(", ");
maybeLineBreak();
}
@Override
void endFunction(boolean statementContext) {
super.endFunction(statementContext);
if (statementContext) {
startNewLine();
}
}
@Override
void beginCaseBody() {
super.beginCaseBody();
indent++;
endLine();
}
@Override
void endCase
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
this.outputCharset = outCharset;
return this;
}
/**
* Whether the input AST guaranteed to be properly formed, fail if it isn't.
*/
Builder setValidation(boolean validation) {
this.validation = validation;
return this;
}
/**
* Generates the source code and returns it.
*/
String build() {
if (root == null) {
throw new IllegalStateException(
"Cannot build without root node being specified");
}
Format outputFormat = outputTypes
? Format.TYPED
: prettyPrint
? Format.PRETTY
: Format.COMPACT;
return toSource(root, outputFormat, lineBreak, lineLengthThreshold,
sourceMap, outputCharset, validation);
}
}
enum Format {
COMPACT,
PRETTY,
TYPED
}
/**
* Converts a tree to js code
*/
private static String toSource(Node root, Format outputFormat,
boolean lineBreak, int lineLengthThreshold,
SourceMap sourceMap,
Charset outputCharset,
boolean validation) {
boolean createSourceMap = (sourceMap != null);
CodeConsumer cp =
outputFormat == Format.COMPACT
? new CompactCodePrinter(
lineBreak, lineLengthThreshold, createSourceMap)
: new PrettyCodePrinter(lineLengthThreshold, createSourceMap);
CodeGenerator cg =
outputFormat == Format.TYPED
? new TypedCodeGenerator(cp, outputCharset)
: new CodeGenerator(cp, outputCharset, validation);
cg.add(root);
String code = ((HasGetCode) cp).getCode();
if (createSourceMap) {
cp.generateSourceMap(sourceMap);
}
return code;
}
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>AnnotationNames();
return annotationNames;
}
private static synchronized void initAnnotationNames() {
if (annotationNames != null) {
return;
}
Set<String> trimmedNames = Sets.newHashSet();
ResourceBundle config = ResourceBundle.getBundle(configResource);
String[] names = config.getString("jsdoc.annotations").split(",");
for (String name : names) {
trimmedNames.add(name.trim());
}
annotationNames = ImmutableSet.copyOf(trimmedNames);
}
/**
* Parses the JavaScript text given by a reader.
*
* @param sourceName The filename.
* @param sourceString Source code from the file.
* @param errorReporter An error.
* @param logger A logger.
* @return The AST of the given text.
* @throws IOException
*/
public static Node parse(String sourceName,
String sourceString,
Config config,
ErrorReporter errorReporter,
Logger logger) throws IOException {
Context cx = Context.enter();
cx.setErrorReporter(errorReporter);
cx.setLanguageVersion(Context.VERSION_1_5);
CompilerEnvirons compilerEnv = new CompilerEnvirons();
compilerEnv.initFromContext(cx);
compilerEnv.setRecordingComments(true);
compilerEnv.setRecordingLocalJsDocComments(true);
compilerEnv.setWarnTrailingComma(true);
if (config.isIdeMode) {
compilerEnv.setReservedKeywordAsIdentifier(true);
compilerEnv.setAllowMemberExprAsFunctionName(true);
}
Parser p = new Parser(compilerEnv, errorReporter);
AstRoot astRoot = null;
try {
astRoot = p.parse(sourceString, sourceName, 1);
} catch (EvaluatorException e) {
logger.info("Error parsing " + sourceName + ": " + e.getMessage());
} finally {
Context.exit();
}
Node root = null;
if (astRoot != null) {
root = IRFactory.transformTree(
astRoot, sourceString, config, errorReporter);
root.setIsSyntheticBlock(true);
}
return root;
}
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
private void mismatch(NodeTraversal t, Node n,
String msg, JSType found, JSTypeNative required) {
mismatch(t, n, msg, found, getNativeType(required));
}
private void mismatch(String sourceName, Node n,
String msg, JSType found, JSType required) {
registerMismatch(found, required);
compiler.report(
JSError.make(sourceName, n, TYPE_MISMATCH_WARNING,
formatFoundRequired(msg, found, required)));
}
private void registerMismatch(JSType found, JSType required) {
// Don't register a mismatch for differences in null or undefined or if the
// code didn't downcast.
found = found.restrictByNotNullOrUndefined();
required = required.restrictByNotNullOrUndefined();
if (found.canAssignTo(required) || required.canAssignTo(found)) {
return;
}
mismatches.add(new TypeMismatch(found, required));
if (found instanceof FunctionType &&
required instanceof FunctionType) {
FunctionType fnTypeA = ((FunctionType) found);
FunctionType fnTypeB = ((FunctionType) required);
Iterator<Node> paramItA = fnTypeA.getParameters().iterator();
Iterator<Node> paramItB = fnTypeB.getParameters().iterator();
while (paramItA.hasNext() && paramItB.hasNext()) {
registerIfMismatch(paramItA.next().getJSType(),
paramItB.next().getJSType());
}
registerIfMismatch(fnTypeA.getReturnType(), fnTypeB.getReturnType());
}
}
private void registerIfMismatch(JSType found, JSType required) {
if (found != null && required != null &&
!found.canAssignTo(required)) {
registerMismatch(found, required);
}
}
/**
* Formats a found/required error message.
*/
private String formatFoundRequired(String description, JSType found,
JSType required) {
return MessageFormat.format(FOUND_REQUIRED, description, found, required);
}
/**
* Given a node, get a human-readable name for the type of that node so
* that will be easy for the programmer to find the original declaration.
*
* For example, if SubFoo's property "
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> +
"var x = a;"
});
}
public void testVarMovement7() {
// Don't move a variable higher in the dependency tree
testSame(createModuleStar(
// m1
"function f() {g();}",
// m2
"function g(){};"));
}
public void testClone1() {
test(createModuleChain(
// m1
"function f(){} f.prototype.clone = function() { return new f };",
// m2
"var a = (new f).clone();"),
new String[] {
// m1
"",
"function f(){} f.prototype.clone = function() { return new f() };" +
// m2
"var a = (new f).clone();"
});
}
public void testClone2() {
test(createModuleChain(
// m1
"function f(){}" +
"f.prototype.cloneFun = function() {" +
" return function() {new f}" +
"};",
// m2
"var a = (new f).cloneFun();"),
new String[] {
// m1
"",
"function f(){}" +
"f.prototype.cloneFun = function() {" +
" return function() {new f}" +
"};" +
// m2
"var a = (new f).cloneFun();"
});
}
public void testEmptyModule() {
// When the dest module is empty, it might try to move the code to the
// one of the modules that the empty module depends on. In some cases
// this might ended up to be the same module as the definition of the code.
// When that happens, CrossMooduleCodeMotion might report a code change
// while nothing is moved. This should not be a problem if we know all
// modules are non-empty.
JSModule m1 = new JSModule("m1");
m1.add(JSSourceFile.fromCode("m1", "function x() {}"));
JSModule empty = new JSModule("empty");
empty.addDependency(m1);
JSModule m2 = new JSModule("m2");
m2.add(JSSourceFile.fromCode("m2", "x()"));
m2.addDependency
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>(empty);
JSModule m3 = new JSModule("m3");
m3.add(JSSourceFile.fromCode("m3", "x()"));
m3.addDependency(empty);
test(new JSModule[] {m1,empty,m2,m3},
new String[] {
"",
"function x() {}",
"x()",
"x()"
});
}
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> = def.getValue();
Node inputValue = dominantReplacements.get(defineName);
Node finalValue = inputValue != null ?
inputValue : info.getLastValue();
if (finalValue != info.initialValue) {
info.initialValueParent.replaceChild(
info.initialValue, finalValue.cloneTree());
compiler.addToDebugLog("Overriding @define variable " + defineName);
changed = changed ||
finalValue.getType() != info.initialValue.getType() ||
!finalValue.isEquivalentTo(info.initialValue);
}
}
if (changed) {
compiler.reportCodeChange();
}
Set<String> unusedReplacements = dominantReplacements.keySet();
unusedReplacements.removeAll(allDefines.keySet());
unusedReplacements.removeAll(KNOWN_DEFINES);
for (String unknownDefine : unusedReplacements) {
compiler.report(JSError.make(UNKNOWN_DEFINE_WARNING, unknownDefine));
}
}
private static String format(MessageFormat format, Object... params) {
return format.format(params);
}
/**
* Finds all defines, and creates a {@link DefineInfo} data structure for
* each one.
* @return A map of {@link DefineInfo} structures, keyed by name.
*/
private Map<String, DefineInfo> collectDefines(Node root,
GlobalNamespace namespace) {
// Find all the global names with a @define annotation
List<Name> allDefines = Lists.newArrayList();
for (Name name : namespace.getNameIndex().values()) {
if (name.docInfo != null && name.docInfo.isDefine()) {
allDefines.add(name);
} else if (name.refs != null) {
for (Ref ref : name.refs) {
Node n = ref.node;
Node parent = ref.node.getParent();
JSDocInfo info = n.getJSDocInfo();
if (info == null &&
parent.getType() == Token.VAR && parent.hasOneChild()) {
info = parent.getJSDocInfo();
}
if (info != null && info.isDefine()) {
allDefines.add(name);
break;
}
}
}
}
CollectDefines pass = new CollectDefines(compiler, all
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> ObjToIntMap implements Serializable
{
static final long serialVersionUID = -1542220580748809402L;
// Map implementation via hashtable,
// follows "The Art of Computer Programming" by Donald E. Knuth
// ObjToIntMap is a copy cat of ObjToIntMap with API adjusted to object keys
public static class Iterator {
Iterator(ObjToIntMap master) {
this.master = master;
}
final void init(Object[] keys, int[] values, int keyCount) {
this.keys = keys;
this.values = values;
this.cursor = -1;
this.remaining = keyCount;
}
public void start() {
master.initIterator(this);
next();
}
public boolean done() {
return remaining < 0;
}
public void next() {
if (remaining == -1) Kit.codeBug();
if (remaining == 0) {
remaining = -1;
cursor = -1;
}else {
for (++cursor; ; ++cursor) {
Object key = keys[cursor];
if (key != null && key != DELETED) {
--remaining;
break;
}
}
}
}
public Object getKey() {
Object key = keys[cursor];
if (key == UniqueTag.NULL_VALUE) { key = null; }
return key;
}
public int getValue() {
return values[cursor];
}
public void setValue(int value) {
values[cursor] = value;
}
ObjToIntMap master;
private int cursor;
private int remaining;
private Object[] keys;
private int[] values;
}
public ObjToIntMap() {
this(4);
}
public ObjToIntMap(int keyCountHint) {
if (keyCountHint < 0) Kit.codeBug();
// Table grow when number of stored keys >= 3/4 of max capacity
int minimalCapacity = keyCountHint * 4 / 3;
int i;
for (i = 2; (1 << i) < minimalCapacity; ++i) { }
power = i;
if (check && power < 2) Kit.codeBug();
}
public boolean isEmpty() {
return key
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>Count == 0;
}
public int size() {
return keyCount;
}
public boolean has(Object key) {
if (key == null) { key = UniqueTag.NULL_VALUE; }
return 0 <= findIndex(key);
}
/**
* Get integer value assigned with key.
* @return key integer value or defaultValue if key is absent
*/
public int get(Object key, int defaultValue) {
if (key == null) { key = UniqueTag.NULL_VALUE; }
int index = findIndex(key);
if (0 <= index) {
return values[index];
}
return defaultValue;
}
/**
* Get integer value assigned with key.
* @return key integer value
* @throws RuntimeException if key does not exist
*/
public int getExisting(Object key) {
if (key == null) { key = UniqueTag.NULL_VALUE; }
int index = findIndex(key);
if (0 <= index) {
return values[index];
}
// Key must exist
Kit.codeBug();
return 0;
}
public void put(Object key, int value) {
if (key == null) { key = UniqueTag.NULL_VALUE; }
int index = ensureIndex(key);
values[index] = value;
}
/**
* If table already contains a key that equals to keyArg, return that key
* while setting its value to zero, otherwise add keyArg with 0 value to
* the table and return it.
*/
public Object intern(Object keyArg) {
boolean nullKey = false;
if (keyArg == null) {
nullKey = true;
keyArg = UniqueTag.NULL_VALUE;
}
int index = ensureIndex(keyArg);
values[index] = 0;
return (nullKey) ? null : keys[index];
}
public void remove(Object key) {
if (key == null) { key = UniqueTag.NULL_VALUE; }
int index = findIndex(key);
if (0 <= index) {
keys[index] = DELETED;
--keyCount;
}
}
public void clear() {
int i = keys.length;
while (i != 0) {
keys
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>[--i] = null;
}
keyCount = 0;
occupiedCount = 0;
}
public Iterator newIterator() {
return new Iterator(this);
}
// The sole purpose of the method is to avoid accessing private fields
// from the Iterator inner class to workaround JDK 1.1 compiler bug which
// generates code triggering VerifierError on recent JVMs
final void initIterator(Iterator i) {
i.init(keys, values, keyCount);
}
/** Return array of present keys */
public Object[] getKeys() {
Object[] array = new Object[keyCount];
getKeys(array, 0);
return array;
}
public void getKeys(Object[] array, int offset) {
int count = keyCount;
for (int i = 0; count != 0; ++i) {
Object key = keys[i];
if (key != null && key != DELETED) {
if (key == UniqueTag.NULL_VALUE) { key = null; }
array[offset] = key;
++offset;
--count;
}
}
}
private static int tableLookupStep(int fraction, int mask, int power) {
int shift = 32 - 2 * power;
if (shift >= 0) {
return ((fraction >>> shift) & mask) | 1;
}
else {
return (fraction & (mask >>> -shift)) | 1;
}
}
private int findIndex(Object key) {
if (keys != null) {
int hash = key.hashCode();
int fraction = hash * A;
int index = fraction >>> (32 - power);
Object test = keys[index];
if (test != null) {
int N = 1 << power;
if (test == key
|| (values[N + index] == hash && test.equals(key)))
{
return index;
}
// Search in table after first failed attempt
int mask = N - 1;
int step = tableLookupStep(fraction, mask, power);
int n = 0;
for (;;) {
if (check) {
if (n >= occupiedCount) Kit.codeBug();
++n;
}
index = (index + step) & mask
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>;
test = keys[index];
if (test == null) {
break;
}
if (test == key
|| (values[N + index] == hash && test.equals(key)))
{
return index;
}
}
}
}
return -1;
}
// Insert key that is not present to table without deleted entries
// and enough free space
private int insertNewKey(Object key, int hash) {
if (check && occupiedCount != keyCount) Kit.codeBug();
if (check && keyCount == 1 << power) Kit.codeBug();
int fraction = hash * A;
int index = fraction >>> (32 - power);
int N = 1 << power;
if (keys[index] != null) {
int mask = N - 1;
int step = tableLookupStep(fraction, mask, power);
int firstIndex = index;
do {
if (check && keys[index] == DELETED) Kit.codeBug();
index = (index + step) & mask;
if (check && firstIndex == index) Kit.codeBug();
} while (keys[index] != null);
}
keys[index] = key;
values[N + index] = hash;
++occupiedCount;
++keyCount;
return index;
}
private void rehashTable() {
if (keys == null) {
if (check && keyCount != 0) Kit.codeBug();
if (check && occupiedCount != 0) Kit.codeBug();
int N = 1 << power;
keys = new Object[N];
values = new int[2 * N];
}
else {
// Check if removing deleted entries would free enough space
if (keyCount * 2 >= occupiedCount) {
// Need to grow: less then half of deleted entries
++power;
}
int N = 1 << power;
Object[] oldKeys = keys;
int[] oldValues = values;
int oldN = oldKeys.length;
keys = new Object[N];
values = new int[2 * N];
int remaining = keyCount;
occupiedCount = keyCount = 0;
for (int i = 0; remaining != 0; ++i) {
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> Object key = oldKeys[i];
if (key != null && key != DELETED) {
int keyHash = oldValues[oldN + i];
int index = insertNewKey(key, keyHash);
values[index] = oldValues[i];
--remaining;
}
}
}
}
// Ensure key index creating one if necessary
private int ensureIndex(Object key) {
int hash = key.hashCode();
int index = -1;
int firstDeleted = -1;
if (keys != null) {
int fraction = hash * A;
index = fraction >>> (32 - power);
Object test = keys[index];
if (test != null) {
int N = 1 << power;
if (test == key
|| (values[N + index] == hash && test.equals(key)))
{
return index;
}
if (test == DELETED) {
firstDeleted = index;
}
// Search in table after first failed attempt
int mask = N - 1;
int step = tableLookupStep(fraction, mask, power);
int n = 0;
for (;;) {
if (check) {
if (n >= occupiedCount) Kit.codeBug();
++n;
}
index = (index + step) & mask;
test = keys[index];
if (test == null) {
break;
}
if (test == key
|| (values[N + index] == hash && test.equals(key)))
{
return index;
}
if (test == DELETED && firstDeleted < 0) {
firstDeleted = index;
}
}
}
}
// Inserting of new key
if (check && keys != null && keys[index] != null)
Kit.codeBug();
if (firstDeleted >= 0) {
index = firstDeleted;
}
else {
// Need to consume empty entry: check occupation level
if (keys == null || occupiedCount * 4 >= (1 << power) * 3) {
// Too litle unused entries: rehash
rehashTable();
return insertNewKey(key, hash);
}
++occupiedCount;
}
keys[index] = key;
values[(1 << power) +
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> index] = hash;
++keyCount;
return index;
}
private void writeObject(ObjectOutputStream out)
throws IOException
{
out.defaultWriteObject();
int count = keyCount;
for (int i = 0; count != 0; ++i) {
Object key = keys[i];
if (key != null && key != DELETED) {
--count;
out.writeObject(key);
out.writeInt(values[i]);
}
}
}
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException
{
in.defaultReadObject();
int writtenKeyCount = keyCount;
if (writtenKeyCount != 0) {
keyCount = 0;
int N = 1 << power;
keys = new Object[N];
values = new int[2 * N];
for (int i = 0; i != writtenKeyCount; ++i) {
Object key = in.readObject();
int hash = key.hashCode();
int index = insertNewKey(key, hash);
values[index] = in.readInt();
}
}
}
// A == golden_ratio * (1 << 32) = ((sqrt(5) - 1) / 2) * (1 << 32)
// See Knuth etc.
private static final int A = 0x9e3779b9;
private static final Object DELETED = new Object();
// Structure of kyes and values arrays (N == 1 << power):
// keys[0 <= i < N]: key value or null or DELETED mark
// values[0 <= i < N]: value of key at keys[i]
// values[N <= i < 2*N]: hash code of key at keys[i-N]
private transient Object[] keys;
private transient int[] values;
private int power;
private int keyCount;
private transient int occupiedCount; // == keyCount + deleted_count
// If true, enables consitency checks
private static final boolean check = false;
/* TEST START
public static void main(String[] args) {
if (!check) {
System.err.println("Set check to true and re-run");
throw new RuntimeException("Set check
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.collect.Lists;
import com.google.javascript.jscomp.CheckLevel;
import java.util.*;
/**
* WarningsGuard that represents just a chain of other guards. For example we
* could have following chain
* 1) all warnings outside of /foo/ should be suppressed
* 2) errors with key JSC_BAR should be marked as warning
* 3) the rest should be reported as error
*
* This class is designed for such behaviour.
*
*
*/
public class ComposeWarningsGuard extends WarningsGuard {
private final List<WarningsGuard> guards;
private static final Comparator<WarningsGuard> guardComparator =
new Comparator<WarningsGuard>() {
@Override
public int compare(WarningsGuard a, WarningsGuard b) {
return a.getPriority() - b.getPriority();
}
};
public ComposeWarningsGuard(List<WarningsGuard> guards) {
this.guards = Lists.newArrayList();
addGuards(guards);
}
public ComposeWarningsGuard(WarningsGuard... guards) {
this(Lists.newArrayList(guards));
}
void addGuard(WarningsGuard guard) {
if (guard instanceof ComposeWarningsGuard) {
addGuards(((ComposeWarningsGuard) guard).guards);
} else {
int index = Collections.binarySearch(this.guards, guard, guardComparator);
if (index < 0) {
index = -index - 1;
}
this.guards.add(index, guard);
}
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> pass being tested. */
private boolean normalizeEnabled = false;
/** Whether the expected js strings should be normalized. */
private boolean normalizeExpected = false;
/** Whether to check that all line number information is preserved. */
private boolean checkLineNumbers = false;
/**
* An expected symbol table error. Only useful for testing the
* symbol table error-handling.
*/
private DiagnosticType expectedSymbolTableError = null;
/**
* Whether the MarkNoSideEffectsCalls pass runs before the pass being tested
*/
private boolean markNoSideEffects = false;
/** The most recently used Compiler instance. */
private Compiler lastCompiler;
/**
* Constructs a test.
*
* @param externs Externs JS as a string
* @param compareAsTree True to compare output & expected as a node tree.
* 99% of the time you want to compare as a tree. There are a few
* special cases where you don't, like if you want to test the code
* printing of "unnatural" syntax trees. For example,
*
* <pre>
* IF
* IF
* STATEMENT
* ELSE
* STATEMENT
* </pre>
*/
protected CompilerTestCase(String externs, boolean compareAsTree) {
this.externsInputs = new JSSourceFile[] {
JSSourceFile.fromCode("externs", externs)
};
this.compareAsTree = compareAsTree;
this.parseTypeInfo = false;
}
/**
* Constructs a test. Uses AST comparison.
* @param externs Externs JS as a string
*/
protected CompilerTestCase(String externs) {
this(externs, true);
}
/**
* Constructs a test. Uses AST comparison and no externs.
*/
protected CompilerTestCase() {
this("", true);
}
/**
* Gets the compiler pass instance to use for a test.
*
* @param compiler The compiler
* @return The pass to test
*/
protected abstract CompilerPass getProcessor(Compiler compiler);
/**
* Gets the compiler options to use for this test. Defaults to do nothing
* options.
*
* This is really only for configuring warnings guards. Use getProcessor
* to determine what passes should be run.
*/
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> is expected
* @param warning Expected warning, or null if no warning is expected
*/
public void test(String js, String expected,
DiagnosticType error, DiagnosticType warning) {
test(externsInputs, js, expected, error, warning, null);
}
/**
* Verifies that the compiler pass's JS output matches the expected output
* and (optionally) that an expected warning is issued. Or, if an error is
* expected, this method just verifies that the error is encountered.
*
* @param externs Externs input
* @param js Input
* @param expected Expected output, or null if an error is expected
* @param error Expected error, or null if no error is expected
* @param warning Expected warning, or null if no warning is expected
*/
public void test(String externs, String js, String expected,
DiagnosticType error, DiagnosticType warning) {
test(externs, js, expected, error, warning, null);
}
/**
* Verifies that the compiler pass's JS output matches the expected output
* and (optionally) that an expected warning is issued. Or, if an error is
* expected, this method just verifies that the error is encountered.
*
* @param externs Externs input
* @param js Input
* @param expected Expected output, or null if an error is expected
* @param error Expected error, or null if no error is expected
* @param warning Expected warning, or null if no warning is expected
* @param description The description of the expected warning,
* or null if no warning is expected or if the warning's description
* should not be examined
*/
public void test(String externs, String js, String expected,
DiagnosticType error, DiagnosticType warning,
String description) {
JSSourceFile[] externsInputs = new JSSourceFile[]{
JSSourceFile.fromCode("externs", externs)
};
test(externsInputs, js, expected, error, warning, description);
}
/**
* Verifies that the compiler pass's JS output matches the expected output
* and (optionally) that an expected warning is issued. Or, if an error is
* expected, this method just verifies that the error is encountered.
*
* @param externs Extern
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>s inputs
* @param js Input
* @param expected Expected output, or null if an error is expected
* @param error Expected error, or null if no error is expected
* @param warning Expected warning, or null if no warning is expected
* @param description The description of the expected warning,
* or null if no warning is expected or if the warning's description
* should not be examined
*/
public void test(JSSourceFile[] externs, String js, String expected,
DiagnosticType error,
DiagnosticType warning, String description) {
Compiler compiler = createCompiler();
lastCompiler = compiler;
BaseJSTypeTestCase.addNativeProperties(compiler.getTypeRegistry());
CompilerOptions options = getOptions();
// Note that in this context, turning on the checkTypes option won't
// actually cause the type check to run.
options.checkTypes = parseTypeInfo;
compiler.init(externs, new JSSourceFile[] {
JSSourceFile.fromCode("testcode", js) }, options);
test(compiler, new String[] { expected }, error, warning, description);
}
/**
* Verifies that the compiler pass's JS output matches the expected output.
*
* @param js Inputs
* @param expected Expected JS output
*/
public void test(String[] js, String[] expected) {
test(js, expected, null);
}
/**
* Verifies that the compiler pass's JS output matches the expected output,
* or that an expected error is encountered.
*
* @param js Inputs
* @param expected Expected JS output
* @param error Expected error, or null if no error is expected
*/
public void test(String[] js, String[] expected, DiagnosticType error) {
test(js, expected, error, null);
}
/**
* Verifies that the compiler pass's JS output matches the expected output
* and (optionally) that an expected warning is issued. Or, if an error is
* expected, this method just verifies that the error is encountered.
*
* @param js Inputs
* @param expected Expected JS output
* @param error Expected error, or null if no error is expected
* @param warning Expected warning, or null if no warning is expected
*/
public void test(String[] js, String[] expected, Diagnostic
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>Type error,
DiagnosticType warning) {
test(js, expected, error, warning, null);
}
/**
* Verifies that the compiler pass's JS output matches the expected output
* and (optionally) that an expected warning is issued. Or, if an error is
* expected, this method just verifies that the error is encountered.
*
* @param js Inputs
* @param expected Expected JS output
* @param error Expected error, or null if no error is expected
* @param warning Expected warning, or null if no warning is expected
* @param description The description of the expected warning,
* or null if no warning is expected or if the warning's description
* should not be examined
*/
public void test(String[] js, String[] expected, DiagnosticType error,
DiagnosticType warning, String description) {
Compiler compiler = createCompiler();
lastCompiler = compiler;
JSSourceFile[] inputs = new JSSourceFile[js.length];
for (int i = 0; i < js.length; i++) {
inputs[i] = JSSourceFile.fromCode("input" + i, js[i]);
}
compiler.init(externsInputs, inputs, getOptions());
test(compiler, expected, error, warning, description);
}
/**
* Verifies that the compiler pass's JS output matches the expected output.
*
* @param modules Module inputs
* @param expected Expected JS outputs (one per module)
*/
public void test(JSModule[] modules, String[] expected) {
test(modules, expected, null);
}
/**
* Verifies that the compiler pass's JS output matches the expected output,
* or that an expected error is encountered.
*
* @param modules Module inputs
* @param expected Expected JS outputs (one per module)
* @param error Expected error, or null if no error is expected
*/
public void test(JSModule[] modules, String[] expected,
DiagnosticType error) {
test(modules, expected, error, null);
}
/**
* Verifies that the compiler pass's JS output matches the expected output
* and (optionally) that an expected warning is issued. Or, if an error is
* expected, this method just verifies that the error is encountered.
*
* @param
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> description is issued.
*
* @param externs Externs input
* @param js Input and output
* @param warning Expected warning, or null if no warning is expected
* @param description The description of the expected warning,
* or null if no warning is expected or if the warning's description
* should not be examined
*/
public void testSame(String externs, String js, DiagnosticType warning,
String description) {
JSSourceFile[] externsInputs = new JSSourceFile[]{
JSSourceFile.fromCode("externs", externs)
};
test(externsInputs, js, js, null, warning, description);
}
/**
* Verifies that the compiler pass's JS output is the same as its input.
*
* @param js Inputs and outputs
*/
public void testSame(String[] js) {
test(js, js);
}
/**
* Verifies that the compiler pass's JS output is the same as its input,
* and emits the given error.
*
* @param js Inputs and outputs
* @param error Expected error, or null if no error is expected
*/
public void testSame(String[] js, DiagnosticType error) {
test(js, js, error);
}
/**
* Verifies that the compiler pass's JS output is the same as its input,
* and emits the given error and warning.
*
* @param js Inputs and outputs
* @param error Expected error, or null if no error is expected
* @param warning Expected warning, or null if no warning is expected
*/
public void testSame(String[] js, DiagnosticType error, DiagnosticType warning) {
test(js, js, error, warning);
}
/**
* Verifies that the compiler pass's JS output is the same as the input.
*
* @param modules Module inputs
*/
public void testSame(JSModule[] modules) {
testSame(modules, null);
}
/**
* Verifies that the compiler pass's JS output is the same as the input.
*
* @param modules Module inputs
* @param warning A warning, or null for no expected warning.
*/
public void testSame(JSModule[] modules, DiagnosticType warning) {
try {
String[] expected = new String[
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>modules.length];
for (int i = 0; i < modules.length; i++) {
expected[i] = "";
for (CompilerInput input : modules[i].getInputs()) {
expected[i] += input.getSourceFile().getCode();
}
}
test(modules, expected, null, warning);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Verifies that the compiler pass's JS output matches the expected output
* and (optionally) that an expected warning is issued. Or, if an error is
* expected, this method just verifies that the error is encountered.
*
* @param compiler A compiler that has been initialized via
* {@link Compiler#init}
* @param expected Expected output, or null if an error is expected
* @param error Expected error, or null if no error is expected
* @param warning Expected warning, or null if no warning is expected
*/
protected void test(Compiler compiler, String[] expected,
DiagnosticType error, DiagnosticType warning) {
test(compiler, expected, error, warning, null);
}
/**
* Verifies that the compiler pass's JS output matches the expected output
* and (optionally) that an expected warning is issued. Or, if an error is
* expected, this method just verifies that the error is encountered.
*
* @param compiler A compiler that has been initialized via
* {@link Compiler#init}
* @param expected Expected output, or null if an error is expected
* @param error Expected error, or null if no error is expected
* @param warning Expected warning, or null if no warning is expected
* @param description The description of the expected warning,
* or null if no warning is expected or if the warning's description
* should not be examined
*/
private void test(Compiler compiler, String[] expected,
DiagnosticType error, DiagnosticType warning,
String description) {
RecentChange recentChange = new RecentChange();
compiler.addChangeHandler(recentChange);
Node root = compiler.parseInputs();
assertTrue("Unexpected parse error(s): " +
Joiner.on("\n").join(compiler.getErrors()), root != null);
Node externsRoot = root.getFirstChild();
Node mainRoot = root.getLastChild
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>();
// Save the tree for later comparison.
Node rootClone = root.cloneTree();
Node externsRootClone = rootClone.getFirstChild();
Node mainRootClone = rootClone.getLastChild();
int numRepetitions = getNumRepetitions();
ErrorManager[] errorManagers = new ErrorManager[numRepetitions];
int aggregateWarningCount = 0;
List<JSError> aggregateWarnings = Lists.newArrayList();
boolean hasCodeChanged = false;
assertFalse("Code should not change before processing",
recentChange.hasCodeChanged());
for (int i = 0; i < numRepetitions; ++i) {
if (compiler.getErrorCount() == 0) {
errorManagers[i] = new BlackHoleErrorManager(compiler);
// Only run the type checking pass once, if asked.
// Running it twice can cause unpredictable behavior because duplicate
// objects for the same type are created, and the type system
// uses reference equality to compare many types.
if (typeCheckEnabled && i == 0) {
TypeCheck check = createTypeCheck(compiler, typeCheckLevel);
check.processForTesting(externsRoot, mainRoot);
}
// Only run the normalize pass once, if asked.
if (normalizeEnabled && i == 0) {
Normalize normalize = new Normalize(compiler, false);
normalize.process(externsRoot, mainRoot);
compiler.setNormalized();
}
if (markNoSideEffects && i == 0) {
MarkNoSideEffectCalls mark = new MarkNoSideEffectCalls(compiler);
mark.process(externsRoot, mainRoot);
}
recentChange.reset();
getProcessor(compiler).process(externsRoot, mainRoot);
if (checkLineNumbers) {
(new LineNumberCheck(compiler)).process(externsRoot, mainRoot);
}
hasCodeChanged = hasCodeChanged || recentChange.hasCodeChanged();
aggregateWarningCount += errorManagers[i].getWarningCount();
aggregateWarnings.addAll(Lists.newArrayList(compiler.getWarnings()));
if (normalizeEnabled) {
boolean verifyDeclaredConstants = true;
new Normalize.VerifyConstants(compiler, verifyDeclaredConstants)
.process(externsRoot, mainRoot);
}
}
}
if (error == null) {
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
assertEquals(
"Unexpected error(s): " + Joiner.on("\n").join(compiler.getErrors()),
0, compiler.getErrorCount());
// Verify the symbol table.
ErrorManager symbolTableErrorManager =
new BlackHoleErrorManager(compiler);
Node expectedRoot = parseExpectedJs(expected);
expectedRoot.detachFromParent();
SymbolTable table = compiler.acquireSymbolTable();
table.verify(
new Node(Token.BLOCK, externsRoot.cloneTree(), expectedRoot),
mainRoot.getParent());
table.release();
JSError[] stErrors = symbolTableErrorManager.getErrors();
if (expectedSymbolTableError != null) {
assertEquals("There should be one error.", 1, stErrors.length);
assertEquals(expectedSymbolTableError, stErrors[0].getType());
} else {
assertEquals("Unexpected symbol table error(s): " +
Joiner.on("\n").join(stErrors),
0, stErrors.length);
}
if (warning == null) {
assertEquals(
"Unexpected warning(s): " + Joiner.on("\n").join(aggregateWarnings),
0, aggregateWarningCount);
} else {
assertEquals("There should be one warning, repeated " + numRepetitions +
" time(s).", numRepetitions, aggregateWarningCount);
for (int i = 0; i < numRepetitions; ++i) {
JSError[] warnings = errorManagers[i].getWarnings();
JSError actual = warnings[0];
assertEquals(warning, actual.getType());
// Make sure that source information is always provided.
if (!allowSourcelessWarnings) {
assertTrue("Missing source file name in warning",
actual.sourceName != null && !actual.sourceName.isEmpty());
assertTrue("Missing line number in warning",
-1 != actual.lineNumber);
assertTrue("Missing char number in warning",
-1 != actual.getCharno());
}
if (description != null) {
assertEquals(description, actual.description);
}
}
}
if (normalizeEnabled) {
Normalize normalize = new Normalize(compiler, false);
normalize.process(externsRootClone, mainRootClone);
}
if (mainRootClone.checkTreeEqualsSilent(mainRoot)) {
assertFalse(
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> + errors,
1, compiler.getErrorCount());
assertEquals(errors, error, compiler.getErrors()[0].getType());
}
}
/**
* Parses expected js inputs and returns the root of the parse tree.
*/
private Node parseExpectedJs(String[] expected) {
Compiler compiler = createCompiler();
JSSourceFile[] inputs = new JSSourceFile[expected.length];
for (int i = 0; i < expected.length; i++) {
inputs[i] = JSSourceFile.fromCode("expected" + i, expected[i]);
}
compiler.init(externsInputs, inputs, getOptions());
Node root = compiler.parseInputs();
assertTrue("Unexpected parse error(s): " +
Joiner.on("\n").join(compiler.getErrors()), root != null);
Node externsRoot = root.getFirstChild();
Node mainRoot = externsRoot.getNext();
// Only run the normalize pass, if asked.
if (normalizeEnabled && normalizeExpected && !compiler.hasErrors()) {
Normalize normalize = new Normalize(compiler, false);
normalize.process(externsRoot, mainRoot);
compiler.setNormalized();
}
return mainRoot;
}
Node parseExpectedJs(String expected) {
return parseExpectedJs(new String[] {expected});
}
/**
* Generates a list of modules from a list of inputs, such that each module
* depends on the module before it.
*/
static JSModule[] createModuleChain(String... inputs) {
JSModule[] modules = createModules(inputs);
for (int i = 1; i < modules.length; i++) {
modules[i].addDependency(modules[i - 1]);
}
return modules;
}
/**
* Generates a list of modules from a list of inputs, such that each module
* depends on the first module.
*/
static JSModule[] createModuleStar(String... inputs) {
JSModule[] modules = createModules(inputs);
for (int i = 1; i < modules.length; i++) {
modules[i].addDependency(modules[0]);
}
return modules;
}
/**
* Generates a list of modules from a list of inputs. Does not generate any
* dependencies between the modules.
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> */
static JSModule[] createModules(String... inputs) {
JSModule[] modules = new JSModule[inputs.length];
for (int i = 0; i < inputs.length; i++) {
JSModule module = modules[i] = new JSModule("m" + i);
module.add(JSSourceFile.fromCode("i" + i, inputs[i]));
}
return modules;
}
private static class BlackHoleErrorManager extends BasicErrorManager {
private BlackHoleErrorManager(Compiler compiler) {
compiler.setErrorManager(this);
}
@Override
public void println(CheckLevel level, JSError error) {}
@Override
public void printSummary() {}
}
private Compiler createCompiler() {
Compiler compiler = new Compiler();
return compiler;
}
protected void setExpectedSymbolTableError(DiagnosticType type) {
this.expectedSymbolTableError = type;
}
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>/*
* Copyright 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.collect.Sets;
import com.google.javascript.jscomp.CheckLevel;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.SortedSet;
/**
* <p>A basic error manager that sorts all errors and warnings reported to it to
* generate a sorted report when the {@link #generateReport()} method
* is called.</p>
*
* <p>This error manager does not produce any output, but subclasses can
* override the {@link #println(CheckLevel, JSError)} method to generate custom
* output.</p>
*
*
*
*/
public abstract class BasicErrorManager implements ErrorManager {
private final SortedSet<ErrorWithLevel> messages =
Sets.newTreeSet(new LeveledJSErrorComparator());
private int errorCount = 0;
private int warningCount = 0;
private double typedPercent = 0.0;
public void report(CheckLevel level, JSError error) {
if (messages.add(new ErrorWithLevel(error, level))) {
if (level == CheckLevel.ERROR) {
errorCount++;
} else if (level == CheckLevel.WARNING) {
warningCount++;
}
}
}
public void generateReport() {
for (ErrorWithLevel message : messages) {
println(message.level, message.error);
}
printSummary();
}
/**
* Print a message with a trailing new line. This method is called by the
* {@link #generate
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>Report()} method when generating messages.
*/
public abstract void println(CheckLevel level, JSError error);
/**
* Print the summary of the compilation - number of errors and warnings.
*/
protected abstract void printSummary();
public int getErrorCount() {
return errorCount;
}
public int getWarningCount() {
return warningCount;
}
public JSError[] getErrors() {
return toArray(CheckLevel.ERROR);
}
public JSError[] getWarnings() {
return toArray(CheckLevel.WARNING);
}
public void setTypedPercent(double typedPercent) {
this.typedPercent = typedPercent;
}
public double getTypedPercent() {
return typedPercent;
}
private JSError[] toArray(CheckLevel level) {
List<JSError> errors = new ArrayList<JSError>(messages.size());
for (ErrorWithLevel p : messages) {
if (p.level == level) {
errors.add(p.error);
}
}
return errors.toArray(new JSError[errors.size()]);
}
/**
* <p>Comparator of {@link JSError} with an associated {@link CheckLevel}.
* The ordering is the standard lexical ordering on the quintuple
* (file name, line number, {@link CheckLevel},
* character number, description).</p>
*
* <p>Note: this comparator imposes orderings that are inconsistent with
* {@link JSError#equals(Object)}.</p>
*/
static final class LeveledJSErrorComparator
implements Comparator<ErrorWithLevel> {
private static final int P1_LT_P2 = -1;
private static final int P1_GT_P2 = 1;
public int compare(ErrorWithLevel p1, ErrorWithLevel p2) {
// null is the smallest value
if (p2 == null) {
if (p1 == null) {
return 0;
} else {
return P1_GT_P2;
}
}
// check level
if (p1.level != p2.level) {
return p2.level.compareTo(p1.level);
}
// sourceName comparison
String source1 = p1.error.sourceName;
String source2
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>658296L;
public ObjArray() { }
public final boolean isSealed()
{
return sealed;
}
public final void seal()
{
sealed = true;
}
public final boolean isEmpty()
{
return size == 0;
}
public final int size()
{
return size;
}
public final void setSize(int newSize)
{
if (newSize < 0) throw new IllegalArgumentException();
if (sealed) throw onSeledMutation();
int N = size;
if (newSize < N) {
for (int i = newSize; i != N; ++i) {
setImpl(i, null);
}
} else if (newSize > N) {
if (newSize > FIELDS_STORE_SIZE) {
ensureCapacity(newSize);
}
}
size = newSize;
}
public final Object get(int index)
{
if (!(0 <= index && index < size)) throw onInvalidIndex(index, size);
return getImpl(index);
}
public final void set(int index, Object value)
{
if (!(0 <= index && index < size)) throw onInvalidIndex(index, size);
if (sealed) throw onSeledMutation();
setImpl(index, value);
}
@SuppressWarnings("fallthrough")
private Object getImpl(int index)
{
switch (index) {
case 0: return f0;
case 1: return f1;
case 2: return f2;
case 3: return f3;
case 4: return f4;
}
return data[index - FIELDS_STORE_SIZE];
}
@SuppressWarnings("fallthrough")
private void setImpl(int index, Object value)
{
switch (index) {
case 0: f0 = value; break;
case 1: f1 = value; break;
case 2: f2 = value; break;
case 3: f3 = value; break;
case 4: f4 = value; break;
default: data[index - FIELDS_STORE_SIZE] = value;
}
}
public int indexOf(Object obj)
{
int N = size;
for (
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>int i = 0; i != N; ++i) {
Object current = getImpl(i);
if (current == obj || (current != null && current.equals(obj))) {
return i;
}
}
return -1;
}
public int lastIndexOf(Object obj)
{
for (int i = size; i != 0;) {
--i;
Object current = getImpl(i);
if (current == obj || (current != null && current.equals(obj))) {
return i;
}
}
return -1;
}
public final Object peek()
{
int N = size;
if (N == 0) throw onEmptyStackTopRead();
return getImpl(N - 1);
}
@SuppressWarnings("fallthrough")
public final Object pop()
{
if (sealed) throw onSeledMutation();
int N = size;
--N;
Object top;
switch (N) {
case -1: throw onEmptyStackTopRead();
case 0: top = f0; f0 = null; break;
case 1: top = f1; f1 = null; break;
case 2: top = f2; f2 = null; break;
case 3: top = f3; f3 = null; break;
case 4: top = f4; f4 = null; break;
default:
top = data[N - FIELDS_STORE_SIZE];
data[N - FIELDS_STORE_SIZE] = null;
}
size = N;
return top;
}
public final void push(Object value)
{
add(value);
}
public final void add(Object value)
{
if (sealed) throw onSeledMutation();
int N = size;
if (N >= FIELDS_STORE_SIZE) {
ensureCapacity(N + 1);
}
size = N + 1;
setImpl(N, value);
}
@SuppressWarnings("fallthrough")
public final void add(int index, Object value)
{
int N = size;
if (!(0 <= index && index <= N)) throw onInvalidIndex(index, N + 1);
if (sealed) throw onSeledMutation();
Object
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
default:
if (index != N) {
System.arraycopy(data, index - FIELDS_STORE_SIZE + 1,
data, index - FIELDS_STORE_SIZE,
N - index);
}
data[N - FIELDS_STORE_SIZE] = null;
}
size = N;
}
public final void clear()
{
if (sealed) throw onSeledMutation();
int N = size;
for (int i = 0; i != N; ++i) {
setImpl(i, null);
}
size = 0;
}
public final Object[] toArray()
{
Object[] array = new Object[size];
toArray(array, 0);
return array;
}
public final void toArray(Object[] array)
{
toArray(array, 0);
}
@SuppressWarnings("fallthrough")
public final void toArray(Object[] array, int offset)
{
int N = size;
switch (N) {
default:
System.arraycopy(data, 0, array, offset + FIELDS_STORE_SIZE,
N - FIELDS_STORE_SIZE);
case 5: array[offset + 4] = f4;
case 4: array[offset + 3] = f3;
case 3: array[offset + 2] = f2;
case 2: array[offset + 1] = f1;
case 1: array[offset + 0] = f0;
case 0: break;
}
}
private void ensureCapacity(int minimalCapacity)
{
int required = minimalCapacity - FIELDS_STORE_SIZE;
if (required <= 0) throw new IllegalArgumentException();
if (data == null) {
int alloc = FIELDS_STORE_SIZE * 2;
if (alloc < required) {
alloc = required;
}
data = new Object[alloc];
} else {
int alloc = data.length;
if (alloc < required) {
if (alloc <= FIELDS_STORE_SIZE) {
alloc = FIELDS_STORE_SIZE * 2;
} else {
alloc *= 2;
}
if (alloc < required) {
alloc = required;
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> Object[] tmp = new Object[alloc];
if (size > FIELDS_STORE_SIZE) {
System.arraycopy(data, 0, tmp, 0,
size - FIELDS_STORE_SIZE);
}
data = tmp;
}
}
}
private static RuntimeException onInvalidIndex(int index, int upperBound)
{
// \u2209 is "NOT ELEMENT OF"
String msg = index+" \u2209 [0, "+upperBound+')';
throw new IndexOutOfBoundsException(msg);
}
private static RuntimeException onEmptyStackTopRead()
{
throw new RuntimeException("Empty stack");
}
private static RuntimeException onSeledMutation()
{
throw new IllegalStateException("Attempt to modify sealed array");
}
private void writeObject(ObjectOutputStream os) throws IOException
{
os.defaultWriteObject();
int N = size;
for (int i = 0; i != N; ++i) {
Object obj = getImpl(i);
os.writeObject(obj);
}
}
private void readObject(ObjectInputStream is)
throws IOException, ClassNotFoundException
{
is.defaultReadObject(); // It reads size
int N = size;
if (N > FIELDS_STORE_SIZE) {
data = new Object[N - FIELDS_STORE_SIZE];
}
for (int i = 0; i != N; ++i) {
Object obj = is.readObject();
setImpl(i, obj);
}
}
// Number of data elements
private int size;
private boolean sealed;
private static final int FIELDS_STORE_SIZE = 5;
private transient Object f0, f1, f2, f3, f4;
private transient Object[] data;
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>'t been filled in for that
* module.
*
* dependencyMap should be filled from leaf to root so that
* getTransitiveDepsDeepestFirst can use its results directly.
*/
private Map<JSModule, Set<JSModule>> dependencyMap = Maps.newHashMap();
/**
* Creates a module graph from a list of modules in dependency order.
*/
public JSModuleGraph(JSModule[] modulesInDepOrder) {
moduleDepths = new HashMap<JSModule, Integer>(modulesInDepOrder.length);
modulesByDepth = new ArrayList<List<JSModule>>();
for (JSModule module : modulesInDepOrder) {
int depth = 0;
for (JSModule dep : module.getDependencies()) {
Integer depDepth = moduleDepths.get(dep);
if (depDepth == null) {
throw new ModuleDependenceException(String.format(
"Modules not in dependency order: %s preceded %s",
module.getName(), dep.getName()),
module, dep);
}
depth = Math.max(depth, depDepth + 1);
}
moduleDepths.put(module, depth);
if (depth == modulesByDepth.size()) {
modulesByDepth.add(new ArrayList<JSModule>());
}
modulesByDepth.get(depth).add(module);
}
}
/**
* Gets an iterable over all modules.
*/
Iterable<JSModule> getAllModules() {
return moduleDepths.keySet();
}
/**
* Gets the total number of modules.
*/
int getModuleCount() {
return moduleDepths.size();
}
/**
* Gets the root module.
*/
JSModule getRootModule() {
return Iterables.getOnlyElement(modulesByDepth.get(0));
}
/**
* Gets the depth of a module.
*
* @param module A module in this graph
* @return The depth of the module
*/
int getDepth(JSModule module) {
return moduleDepths.get(module);
}
/**
* Determines whether this module depends on a given module. Note that a
* module never depends on itself, as that dependency would be cyclic.
*/
public boolean dependsOn(JSModule src, JSModule m) {
Set
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS><JSModule> deps = dependencyMap.get(src);
if (deps == null) {
deps = getTransitiveDepsDeepestFirst(src);
dependencyMap.put(src, deps);
}
return deps.contains(m);
}
/**
* Finds the deepest common dependency of two modules, not including the two
* modules themselves.
*
* @param m1 A module in this graph
* @param m2 A module in this graph
* @return The deepest common dep of {@code m1} and {@code m2}, or null if
* they have no common dependencies
*/
JSModule getDeepestCommonDependency(JSModule m1, JSModule m2) {
int m1Depth = getDepth(m1);
int m2Depth = getDepth(m2);
// According our definition of depth, the result must have a strictly
// smaller depth than either m1 or m2.
for (int depth = Math.min(m1Depth, m2Depth) - 1; depth >= 0; depth--) {
List<JSModule> modulesAtDepth = modulesByDepth.get(depth);
// Look at the modules at this depth in reverse order, so that we use the
// original ordering of the modules to break ties (later meaning deeper).
for (int i = modulesAtDepth.size() - 1; i >= 0; i--) {
JSModule m = modulesAtDepth.get(i);
if (dependsOn(m1, m) && dependsOn(m2, m)) {
return m;
}
}
}
return null;
}
/**
* Finds the deepest common dependency of two modules, including the
* modules themselves.
*
* @param m1 A module in this graph
* @param m2 A module in this graph
* @return The deepest common dep of {@code m1} and {@code m2}, or null if
* they have no common dependencies
*/
public JSModule getDeepestCommonDependencyInclusive(
JSModule m1, JSModule m2) {
if (m2 == m1 || dependsOn(m2, m1)) {
return m1;
} else if (dependsOn(m1, m2
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>)) {
return m2;
}
return getDeepestCommonDependency(m1, m2);
}
/** Returns the deepest common dependency of the given modules. */
public JSModule getDeepestCommonDependencyInclusive(
Collection<JSModule> modules) {
Iterator<JSModule> iter = modules.iterator();
JSModule dep = iter.next();
while (iter.hasNext()) {
dep = getDeepestCommonDependencyInclusive(dep, iter.next());
}
return dep;
}
/**
* Creates an iterable over the transitive dependencies of module {@code m}
* in a non-increasing depth ordering. The result does not include the module
* {@code m}.
*
* @param m A module in this graph
* @return The transitive dependencies of module {@code m}
*/
Set<JSModule> getTransitiveDepsDeepestFirst(JSModule m) {
Set<JSModule> deps = dependencyMap.get(m);
if (deps != null) {
return deps;
}
deps = new TreeSet<JSModule>(new InverseDepthComparator());
addDeps(deps, m);
dependencyMap.put(m, deps);
return deps;
}
/**
* Adds a module's transitive dependencies to a set.
*/
private void addDeps(Set<JSModule> deps, JSModule m) {
for (JSModule dep : m.getDependencies()) {
deps.add(dep);
addDeps(deps, dep);
}
}
/**
* Replaces any files that are found multiple times with a single instance in
* the closest parent module that is common to all modules where it appears.
*
* JSCompiler normally errors if you attempt to compile modules containing the
* same file. This method can be used to remove duplicates before compiling
* to avoid such an error.
*/
public void coalesceDuplicateFiles() {
Multimap<String, JSModule> fileRefs = LinkedHashMultimap.create();
for (JSModule module : moduleDepths.keySet()) {
for (CompilerInput jsFile : module.getInputs()) {
fileRefs.put(jsFile.getName(), module);
}
}
for (String path : fileRefs.keySet()) {
Collection<JSModule> ref
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>Modules = fileRefs.get(path);
if (refModules.size() > 1) {
JSModule depModule = getDeepestCommonDependencyInclusive(refModules);
CompilerInput file = refModules.iterator().next().getByName(path);
for (JSModule module : refModules) {
if (module != depModule) {
module.removeByName(path);
}
}
if (!refModules.contains(depModule)) {
depModule.add(file);
}
}
}
}
/**
* A module depth comparator that considers a deeper module to be "less than"
* a shallower module. Uses module names to consistently break ties.
*/
private class InverseDepthComparator implements Comparator<JSModule> {
public int compare(JSModule m1, JSModule m2) {
if (m1 == m2) {
return 0;
}
int d1 = getDepth(m1);
int d2 = getDepth(m2);
return d2 < d1 ? -1 : d2 == d1 ? m2.getName().compareTo(m1.getName()) : 1;
}
}
/*
* Exception class for declaring when the modules being fed into a
* JSModuleGraph as input aren't in dependence order, and so can't be
* processed for caching of various dependency-related queries.
*/
protected static class ModuleDependenceException
extends IllegalArgumentException {
private static final long serialVersionUID = 1;
private final JSModule module;
private final JSModule dependentModule;
protected ModuleDependenceException(String message,
JSModule module, JSModule dependentModule) {
super(message);
this.module = module;
this.dependentModule = dependentModule;
}
public JSModule getModule() {
return module;
}
public JSModule getDependentModule() {
return dependentModule;
}
}
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>/*
* Copyright 2005 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A JavaScript module has a unique name, consists of a list of compiler inputs,
* and can depend on other modules.
*
*
*
*/
public class JSModule {
/** Module name */
private final String name;
/** Source code inputs */
private final List<CompilerInput> inputs = new ArrayList<CompilerInput>();
/** Modules that this module depends on */
private final List<JSModule> deps = new ArrayList<JSModule>();
/**
* Creates an instance.
*
* @param name A unique name for the module
*/
public JSModule(String name) {
this.name = name;
}
/** Gets the module name. */
public String getName() {
return name;
}
/** Adds a source file input to this module. */
public void add(JSSourceFile file) {
add(new CompilerInput(file));
}
/** Adds a source file input to this module. */
public void addFirst(JSSourceFile file) {
addFirst(new CompilerInput(file));
}
/** Adds a source code input to this module. */
public void add(CompilerInput input) {
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
inputs.add(input);
input.setModule(this);
}
/** Adds a source code input to this module. */
public void addFirst(CompilerInput input) {
inputs.add(0, input);
input.setModule(this);
}
/** Adds a source code input to this module directly after other. */
public void addAfter(CompilerInput input, CompilerInput other) {
Preconditions.checkState(inputs.contains(other));
inputs.add(inputs.indexOf(other), input);
input.setModule(this);
}
/** Adds a dependency on another module. */
public void addDependency(JSModule dep) {
Preconditions.checkState(dep != this);
deps.add(dep);
}
/** Removes all of the inputs from this module. */
public void removeAll() {
for (CompilerInput input : inputs) {
input.setModule(null);
}
inputs.clear();
}
/**
* Gets the list of modules that this module depends on.
*
* @return A list that may be empty but not null
*/
public List<JSModule> getDependencies() {
return deps;
}
/**
* Returns the transitive closure of dependencies starting from the
* dependencies of this module.
*/
public Set<JSModule> getAllDependencies() {
Set<JSModule> allDeps = Sets.newHashSet(deps);
List<JSModule> workList = Lists.newArrayList(deps);
while (workList.size() > 0) {
JSModule module = workList.remove(workList.size() - 1);
for (JSModule dep : module.getDependencies()) {
if (allDeps.add(dep)) {
workList.add(dep);
}
}
}
return allDeps;
}
/** Returns this module and all of its dependencies in one list. */
public Set<JSModule> getThisAndAllDependencies() {
Set<JSModule> deps = getAllDependencies();
deps.add(this);
return deps;
}
/**
* Gets this module's list of source code inputs.
*
* @return A list that may be empty but not null
*/
public List<CompilerInput> getInputs() {
return inputs;
}
/** Returns the input with the
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> Returns the given collection of modules in topological order.
*
* Note that this will return the modules in the same order if they are
* already sorted, and in general, will only change the order as necessary to
* satisfy the ordering dependencies. This can be important for cases where
* the modules do not properly specify all dependencies.
*/
public static JSModule[] sortJsModules(Collection<JSModule> modules) {
List<JSModule> list = Lists.newArrayList();
Set<JSModule> set = Sets.newHashSet();
for (JSModule module : modules) {
addModuleAndDeps(module, list, set, Sets.<JSModule>newHashSet());
}
return list.toArray(new JSModule[list.size()]);
}
/**
* Adds the given input and its deps to the given list and set, if they are
* not already added, placing dependencies before dependants.
*/
private static void addInputAndDeps(
CompilerInput input, Map<String, CompilerInput> provides,
Compiler compiler, List<CompilerInput> list, Set<CompilerInput> set,
Set<CompilerInput> inProgress) {
if (!set.contains(input)) {
if (inProgress.contains(input)) {
throw new IllegalArgumentException(
"Circular dependency involving input: " + input.getName());
}
inProgress.add(input);
for (String require : input.getRequires(compiler)) {
if (provides.containsKey(require)) {
addInputAndDeps(provides.get(require), provides, compiler, list, set,
inProgress);
}
}
list.add(input);
set.add(input);
}
}
/**
* Adds the given module and its deps to the given list and set, if they are
* not already added, placing dependencies before dependants.
*/
private static void addModuleAndDeps(
JSModule module, List<JSModule> list, Set<JSModule> set,
Set<JSModule> inProgress) {
if (!set.contains(module)) {
if (inProgress.contains(module)) {
throw new IllegalArgumentException(
"Circular dependency involving module: " + module.getName());
}
inProgress.add(module);
for (JSModule dep : module.getDependencies()) {
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
addModuleAndDeps(dep, list, set, inProgress);
}
list.add(module);
set.add(module);
}
}
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> data structures cached by this table.
*/
private static class MemoizedData {
private Map<Node, Scope> scopes = Maps.newHashMap();
}
//----------------------------------------------------------------------------
// Verification of consistency. Only for tests.
/**
* Check that this symbol table has been kept up to date. Compiler warnings
* will be emitted if anything is wrong.
* @param expectedRoot The root of the expected AST.
* @param actualRoot The root of the actual AST used with this symbol table.
*/
void verify(Node expectedRoot, Node actualRoot) {
VerifyingCallback callback = new VerifyingCallback(
expectedRoot, actualRoot);
callback.verify();
}
/**
* A callback that traverses an AST root and builds all the
* secondary data structures for it.
*/
private class VerifyingCallback implements ScopedCallback {
private final List<Scope> expectedScopes = Lists.newArrayList();
private final List<Scope> actualScopes = Lists.newArrayList();
private boolean collectingExpected = true;
private final Node actualRoot;
private final Node expectedRoot;
private VerifyingCallback(Node expectedRoot, Node actualRoot) {
this.actualRoot = actualRoot;
this.expectedRoot = expectedRoot;
}
@Override
public boolean shouldTraverse(
NodeTraversal nodeTraversal, Node n, Node parent) {
return true;
}
@Override
public void visit(NodeTraversal t, Node n, Node parent) {}
@Override
public void enterScope(NodeTraversal t) {}
@Override
public void exitScope(NodeTraversal t) {
if (collectingExpected) {
expectedScopes.add(t.getScope());
} else {
actualScopes.add(t.getScope());
}
}
private void verify() {
if (cache == null) {
// The symbol table was never used, so no need to check anything.
return;
}
if (!cache.scopes.isEmpty()) {
verifyScopes();
}
}
private void verifyScopes() {
collectingExpected = true;
NodeTraversal.traverse(compiler, expectedRoot, this);
collectingExpected = false;
(new NodeTraversal(compiler, this, SymbolTable.this))
.traverse(actualRoot);
// This must be true unless something went horribly, horribly wrong.
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
Preconditions.checkState(expectedScopes.size() == actualScopes.size());
for (int i = 0; i < expectedScopes.size(); i++) {
Scope expectedScope = expectedScopes.get(i);
Scope actualScope = actualScopes.get(i);
if (!checkNodesMatch(expectedScope.getRootNode(),
actualScope.getRootNode())) {
compiler.report(
JSError.make(
SCOPE_MISMATCH,
expectedScope.getRootNode().toStringTree(),
actualScope.getRootNode().toStringTree()));
continue;
}
if (expectedScope.getVarCount() != actualScope.getVarCount()) {
compiler.report(
JSError.make(
VARIABLE_COUNT_MISMATCH,
Integer.toString(expectedScope.getVarCount()),
Integer.toString(actualScope.getVarCount())));
} else {
Iterator<Var> it = expectedScope.getVars();
while (it.hasNext()) {
Var var = it.next();
Scope.Var actualVar = actualScope.getVar(var.getName());
if (actualVar == null ||
expectedScope.getVar(var.getName()) != var) {
compiler.report(
JSError.make(MISSING_VARIABLE, var.getName()));
} else if (
!checkNodesMatch(
var.getNameNode(),
actualVar.getNameNode()) ||
!isNodeAttached(actualVar.getNameNode())) {
compiler.report(
JSError.make(MOVED_VARIABLE, var.getName()));
}
}
}
}
}
/**
* Check that the two nodes have the same relative position in the tree.
*/
private boolean checkNodesMatch(Node nodeA, Node nodeB) {
Node currentA = nodeA;
Node currentB = nodeB;
while (currentA != null && currentB != null) {
if (currentA.getType() != currentB.getType() ||
!currentA.isEquivalentTo(currentB)) {
return false;
}
currentA = currentA.getParent();
currentB = currentB.getParent();
}
return currentA == null && currentB == null;
}
private boolean isNodeAttached(Node node) {
// Make sure the cached var is still attached.
for (Node current = node;
current != null; current
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
node.addChildToBack(c);
}
if (skipCount > 0) {
int[] skipIndexes = new int[skipCount];
int i = 0;
int j = 0;
for (Node child : node.children()) {
if (child.getType() == Token.EMPTY) {
node.removeChild(child);
skipIndexes[j] = i;
j++;
}
i++;
}
node.putProp(Node.SKIP_INDEXES_PROP, skipIndexes);
}
return node;
}
@Override
Node processAssignment(Assignment assignmentNode) {
return processInfixExpression(assignmentNode);
}
@Override
Node processAstRoot(AstRoot rootNode) {
Node node = new ScriptOrFnNode(Token.SCRIPT);
for (com.google.javascript.jscomp.mozilla.rhino.Node child : rootNode) {
node.addChildToBack(transform((AstNode)child));
}
parseDirectives(node);
return node;
}
/**
* Parse the directives, encode them in the AST, and remove their nodes.
*
* For information on ES5 directives, see section 14.1 of
* Ecma-262, Edition 5.
*
* It would be nice if Rhino would eventually take care of this for
* us, but right now their directive-processing is a one-off.
*/
private void parseDirectives(Node node) {
// Remove all the directives, and encode them in the AST.
Set<String> directives = null;
while (isDirective(node.getFirstChild())) {
String directive = node.removeFirstChild().getFirstChild().getString();
if (directives == null) {
directives = Sets.newHashSet(directive);
} else {
directives.add(directive);
}
}
if (directives != null) {
node.setDirectives(directives);
}
}
private boolean isDirective(Node n) {
if (n == null) return false;
int nType = n.getType();
return (nType == Token.EXPR_RESULT || nType == Token.EXPR_VOID) &&
n.getFirstChild().getType() == Token.STRING &&
ALLOWED_DIRECTIVES.contains(n.getFirstChild
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> source = getSource();
String sourceExcerpt = source == null ? null :
excerpt.get(
source, error.sourceName, error.lineNumber, excerptFormatter);
// formatting the message
StringBuilder b = new StringBuilder();
if (error.sourceName != null) {
b.append(error.sourceName);
if (error.lineNumber > 0) {
b.append(':');
b.append(error.lineNumber);
}
b.append(": ");
}
b.append(getLevelName(warning ? CheckLevel.WARNING : CheckLevel.ERROR));
b.append(" - ");
b.append(error.description);
b.append('\n');
if (sourceExcerpt != null) {
b.append(sourceExcerpt);
b.append('\n');
int charno = error.getCharno();
// padding equal to the excerpt and arrow at the end
if (excerpt.equals(LINE)
&& 0 <= charno && charno < sourceExcerpt.length()) {
for (int i = 0; i < charno; i++) {
char c = sourceExcerpt.charAt(i);
if (Character.isWhitespace(c)) {
b.append(c);
} else {
b.append(' ');
}
}
b.append("^\n");
}
}
return b.toString();
}
/**
* Formats a region by appending line numbers in front, e.g.
* <pre> 9| if (foo) {
* 10| alert('bar');
* 11| }</pre>
* and return line excerpt without any modification.
*/
static class LineNumberingFormatter implements ExcerptFormatter {
public String formatLine(String line, int lineNumber) {
return line;
}
public String formatRegion(Region region) {
if (region == null) {
return null;
}
String code = region.getSourceExcerpt();
if (code.length() == 0) {
return null;
}
// max length of the number display
int numberLength = Integer.toString(region.getEndingLineNumber())
.length();
// formatting
StringBuilder builder = new StringBuilder(code.length() * 2);
int
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> /**
* Gets the number of properties of this object.
*/
@Override
public int getPropertiesCount() {
ObjectType implicitPrototype = getImplicitPrototype();
if (implicitPrototype == null) {
return this.properties.size();
}
int localCount = 0;
for (String property : properties.keySet()) {
if (!implicitPrototype.hasProperty(property)) {
localCount++;
}
}
return implicitPrototype.getPropertiesCount() + localCount;
}
@Override
public boolean hasProperty(String propertyName) {
if (properties.get(propertyName) != null) {
return true;
}
ObjectType implicitPrototype = getImplicitPrototype();
if (implicitPrototype != null) {
return implicitPrototype.hasProperty(propertyName);
}
return false;
}
@Override
public boolean hasOwnProperty(String propertyName) {
return properties.get(propertyName) != null;
}
@Override
public Set<String> getOwnPropertyNames() {
return properties.keySet();
}
@Override
public boolean isPropertyTypeDeclared(String property) {
Property p = properties.get(property);
if (p == null) {
ObjectType implicitPrototype = getImplicitPrototype();
if (implicitPrototype != null) {
return implicitPrototype.isPropertyTypeDeclared(property);
}
// property does not exist
return false;
}
return !p.inferred;
}
@Override
protected void collectPropertyNames(Set<String> props) {
for (String prop : properties.keySet()) {
props.add(prop);
}
ObjectType implicitPrototype = getImplicitPrototype();
if (implicitPrototype != null) {
implicitPrototype.collectPropertyNames(props);
}
}
@Override
public boolean isPropertyTypeInferred(String property) {
Property p = properties.get(property);
if (p == null) {
ObjectType implicitPrototype = getImplicitPrototype();
if (implicitPrototype != null) {
return implicitPrototype.isPropertyTypeInferred(property);
}
// property does not exist
return false;
}
return p.inferred;
}
@Override
public JSType getPropertyType(String propertyName) {
Property p = properties.get(propertyName);
if (p != null) {
return p.type;
}
ObjectType implicitPrototype = getImplicit
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
return;
}
// resolving component by component
for (int i = 1; i < componentNames.length; i++) {
ObjectType parentClass = ObjectType.cast(value);
if (parentClass == null) {
handleUnresolvedType(t);
return;
}
if (componentNames[i].length() == 0) {
handleUnresolvedType(t);
return;
}
value = parentClass.getPropertyType(componentNames[i]);
}
// last component of the chain
if (value instanceof FunctionType) {
FunctionType functionType = (FunctionType)value;
if (functionType.isConstructor() || functionType.isInterface()) {
setReferencedType(functionType.getInstanceType(), t, enclosing);
} else {
handleUnresolvedType(t);
}
} else if (value instanceof EnumType) {
setReferencedType(((EnumType) value).getElementsType(), t, enclosing);
} else {
handleUnresolvedType(t);
}
}
private void setReferencedType(ObjectType type, ErrorReporter t,
StaticScope<JSType> enclosing) {
referencedType = type;
checkEnumElementCycle(t);
setResolvedTypeInternal(referencedType);
}
private void handleTypeCycle(ErrorReporter t) {
referencedType = registry.getNativeObjectType(JSTypeNative.UNKNOWN_TYPE);
t.warning("Cycle detected in inheritance chain of type " + reference,
sourceName, lineno, null, charno);
setResolvedTypeInternal(referencedType);
}
private void checkEnumElementCycle(ErrorReporter t) {
if (referencedType instanceof EnumElementType &&
((EnumElementType) referencedType).getPrimitiveType() == this) {
handleTypeCycle(t);
}
}
// Warns about this type being unresolved iff it's not a forward-declared
// type name.
private void handleUnresolvedType(ErrorReporter t) {
if (!registry.isForwardDeclaredType(reference) && !forgiving &&
registry.isLastGeneration()) {
t.warning("Unknown type " + reference, sourceName, lineno, null,
charno);
} else {
referencedType = registry.getNativeObjectType(
JSTypeNative.CHECKED_UNKNOWN_TYPE);
}
setResolvedType
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.jstype.FunctionType;
import com.google.javascript.rhino.jstype.JSType;
import com.google.javascript.rhino.jstype.ObjectType;
import java.nio.charset.Charset;
/**
* A code generator that outputs type annotations for functions and
* constructors.
*
*/
class TypedCodeGenerator extends CodeGenerator {
TypedCodeGenerator(CodeConsumer consumer, Charset outputCharset) {
super(consumer, outputCharset, true);
}
@Override
void add(Node n, Context context) {
Node parent = n.getParent();
if (parent.getType() == Token.BLOCK || parent.getType() == Token.SCRIPT) {
if (n.getType() == Token.FUNCTION) {
add(getFunctionAnnotation(n));
} else if (n.getType() == Token.EXPR_RESULT
&& n.getFirstChild().getType() == Token.ASSIGN) {
Node rhs = n.getFirstChild().getFirstChild();
add(getTypeAnnotation(rhs));
} else if (n.getType() == Token.VAR
&& n.getFirstChild().getFirstChild() != null
&& n.getFirstChild().getFirstChild().getType() == Token.FUNCTION) {
add(getFunctionAnnotation(n.getFirstChild().getFirstChild()));
}
}
super.add(n, context);
}
private String getTypeAnnotation(Node node) {
JSType type = node.getJSType();
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> private VariableMap anonymousFunctionNameMap = null;
/** Fully qualified function names and globally unique ids */
private FunctionNames functionNames = null;
public DefaultPassConfig(CompilerOptions options) {
super(options);
}
@Override
State getIntermediateState() {
return new State(
cssNames == null ? null : Maps.newHashMap(cssNames),
exportedNames == null ? null :
Collections.unmodifiableSet(exportedNames),
crossModuleIdGenerator, variableMap, propertyMap,
anonymousFunctionNameMap, functionNames);
}
@Override
void setIntermediateState(State state) {
this.cssNames = state.cssNames == null ? null :
Maps.newHashMap(state.cssNames);
this.exportedNames = state.exportedNames == null ? null :
Sets.newHashSet(state.exportedNames);
this.crossModuleIdGenerator = state.crossModuleIdGenerator;
this.variableMap = state.variableMap;
this.propertyMap = state.propertyMap;
this.anonymousFunctionNameMap = state.anonymousFunctionNameMap;
this.functionNames = state.functionNames;
}
@Override
protected List<PassFactory> getChecks() {
List<PassFactory> checks = Lists.newArrayList();
if (options.nameAnonymousFunctionsOnly) {
if (options.anonymousFunctionNaming ==
AnonymousFunctionNamingPolicy.MAPPED) {
checks.add(nameMappedAnonymousFunctions);
} else if (options.anonymousFunctionNaming ==
AnonymousFunctionNamingPolicy.UNMAPPED) {
checks.add(nameUnmappedAnonymousFunctions);
}
return checks;
}
if (options.checkSuspiciousCode) {
checks.add(suspiciousCode);
}
if (options.checkControlStructures) {
checks.add(checkControlStructures);
}
if (options.checkRequires.isOn()) {
checks.add(checkRequires);
}
if (options.checkProvides.isOn()) {
checks.add(checkProvides);
}
// The following passes are more like "preprocessor" passes.
// It's important that they run before most checking passes.
// Perhaps this method should be renamed?
if (options.generateExports) {
checks.add(generateExports);
}
if (options.exportTestFunctions) {
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
checks.add(exportTestFunctions);
}
if (options.closurePass) {
checks.add(closurePrimitives.makeOneTimePass());
}
if (options.closurePass && options.checkMissingGetCssNameLevel.isOn()) {
checks.add(closureCheckGetCssName);
}
if (options.closurePass) {
checks.add(closureReplaceGetCssName);
}
if (options.syntheticBlockStartMarker != null) {
// This pass must run before the first fold constants pass.
checks.add(createSyntheticBlocks);
}
// All passes must run the variable check. This synthesizes
// variables later so that the compiler doesn't crash. It also
// checks the externs file for validity. If you don't want to warn
// about missing variable declarations, we shut that specific
// error off.
WarningsGuard warningsGuard = options.getWarningsGuard();
if (!options.checkSymbols &&
(warningsGuard == null || !warningsGuard.disables(
DiagnosticGroups.CHECK_VARIABLES))) {
options.setWarningLevel(DiagnosticGroups.CHECK_VARIABLES,
CheckLevel.OFF);
}
checks.add(checkVars);
if (options.checkShadowVars.isOn()) {
checks.add(checkShadowVars);
}
if (options.aggressiveVarCheck.isOn()) {
checks.add(checkVariableReferences);
}
// This pass should run before types are assigned.
if (options.processObjectPropertyString) {
checks.add(objectPropertyStringPreprocess);
}
// DiagnosticGroups override the plain checkTypes option.
if (options.enables(DiagnosticGroups.CHECK_TYPES)) {
options.checkTypes = true;
} else if (options.disables(DiagnosticGroups.CHECK_TYPES)) {
options.checkTypes = false;
}
// Type-checking already does more accurate method arity checking, so don't
// do legacy method arity checking unless checkTypes is OFF.
if (options.checkTypes) {
checks.add(resolveTypes.makeOneTimePass());
checks.add(inferTypes.makeOneTimePass());
checks.add(checkTypes.makeOneTimePass());
} else {
if (options.checkFunctions.isOn()) {
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> checks.add(checkFunctions);
}
if (options.checkMethods.isOn()) {
checks.add(checkMethods);
}
}
if (options.checkUnreachableCode.isOn() ||
(options.checkTypes && options.checkMissingReturn.isOn())) {
checks.add(checkControlFlow);
}
// CheckAccessControls only works if check types is on.
if (options.enables(DiagnosticGroups.ACCESS_CONTROLS)
&& options.checkTypes) {
checks.add(checkAccessControls);
}
if (options.checkGlobalNamesLevel.isOn()) {
checks.add(checkGlobalNames);
}
if (options.checkUndefinedProperties.isOn() ||
options.checkUnusedPropertiesEarly) {
checks.add(checkSuspiciousProperties);
}
if (options.checkCaja || options.checkEs5Strict) {
checks.add(checkStrictMode);
}
// Defines in code always need to be processed.
checks.add(processDefines);
if (options.instrumentationTemplate != null ||
options.recordFunctionInformation) {
checks.add(computeFunctionNames);
}
assertAllOneTimePasses(checks);
return checks;
}
@Override
protected List<PassFactory> getOptimizations() {
List<PassFactory> passes = Lists.newArrayList();
// TODO(nicksantos): The order of these passes makes no sense, and needs
// to be re-arranged.
if (options.runtimeTypeCheck) {
passes.add(runtimeTypeCheck);
}
passes.add(createEmptyPass("beforeStandardOptimizations"));
if (!options.idGenerators.isEmpty()) {
passes.add(replaceIdGenerators);
}
// Optimizes references to the arguments variable.
if (options.optimizeArgumentsArray) {
passes.add(optimizeArgumentsArray);
}
// Remove all parameters that are constants or unused.
if (options.optimizeParameters) {
passes.add(removeUselessParameters);
}
// Abstract method removal works best on minimally modified code, and also
// only needs to run once.
if (options.closurePass && options.removeAbstractMethods) {
passes.add(removeAbstractMethods);
}
// Collapsing properties can undo constant
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> inlining, so we do this before
// the main optimization loop.
if (options.collapseProperties) {
passes.add(collapseProperties);
}
// Tighten types based on actual usage.
if (options.tightenTypes) {
passes.add(tightenTypesBuilder);
}
// Property disambiguation should only run once and needs to be done
// soon after type checking, both so that it can make use of type
// information and so that other passes can take advantage of the renamed
// properties.
if (options.disambiguateProperties) {
passes.add(disambiguateProperties);
}
if (options.computeFunctionSideEffects) {
passes.add(markPureFunctions);
} else if (options.markNoSideEffectCalls) {
// TODO(user) The properties that this pass adds to CALL and NEW
// AST nodes increase the AST's in-memory size. Given that we are
// already running close to our memory limits, we could run into
// trouble if we end up using the @nosideeffects annotation a lot
// or compute @nosideeffects annotations by looking at function
// bodies. It should be easy to propagate @nosideeffects
// annotations as part of passes that depend on this property and
// store the result outside the AST (which would allow garbage
// collection once the pass is done).
passes.add(markNoSideEffectCalls);
}
if (options.chainCalls) {
passes.add(chainCalls);
}
// Constant checking must be done after property collapsing because
// property collapsing can introduce new constants (e.g. enum values).
if (options.inlineConstantVars) {
passes.add(checkConsts);
}
// The Caja library adds properties to Object.prototype, which breaks
// most for-in loops. This adds a check to each loop that skips
// any property matching /___$/.
if (options.ignoreCajaProperties) {
passes.add(ignoreCajaProperties);
}
assertAllOneTimePasses(passes);
if (options.smartNameRemoval || options.reportPath != null) {
passes.addAll(getCodeRemovingPasses());
passes.add(smartNamePass);
}
// TODO(user): This forces a
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> first crack at crossModuleCodeMotion
// before devirtualization. Once certain functions are devirtualized,
// it confuses crossModuleCodeMotion ability to recognized that
// it is recursive.
// TODO(user): This is meant for a temporary quick win.
// In the future, we might want to improve our analysis in
// CrossModuleCodeMotion so we don't need to do this.
if (options.crossModuleCodeMotion) {
passes.add(crossModuleCodeMotion);
}
// Method devirtualization benefits from property disambiguiation so
// it should run after that pass but before passes that do
// optimizations based on global names (like cross module code motion
// and inline functions). Smart Name Removal does better if run before
// this pass.
if (options.devirtualizePrototypeMethods) {
passes.add(devirtualizePrototypeMethods);
}
if (options.customPasses != null) {
passes.add(getCustomPasses(
CustomPassExecutionTime.BEFORE_OPTIMIZATION_LOOP));
}
passes.add(createEmptyPass("beforeMainOptimizations"));
passes.addAll(getMainOptimizationLoop());
passes.add(createEmptyPass("beforeModuleMotion"));
if (options.crossModuleCodeMotion) {
passes.add(crossModuleCodeMotion);
}
if (options.crossModuleMethodMotion) {
passes.add(crossModuleMethodMotion);
}
passes.add(createEmptyPass("afterModuleMotion"));
// Some optimizations belong outside the loop because running them more
// than once would either have no benefit or be incorrect.
if (options.customPasses != null) {
passes.add(getCustomPasses(
CustomPassExecutionTime.AFTER_OPTIMIZATION_LOOP));
}
if (options.flowSensitiveInlineVariables) {
passes.add(flowSensitiveInlineVariables);
// After inlining some of the variable uses, some variables are unused.
// Re-run remove unused vars to clean it up.
if (options.removeUnusedVars) {
passes.add(removeUnusedVars);
}
}
if (options.collapseAnonymousFunctions) {
passes.add(collapseAnonymousFunctions);
}
// Move functions before extracting prototype member declarations.
if (options.moveFunctionDeclarations) {
passes
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>.add(moveFunctionDeclarations);
}
if (options.anonymousFunctionNaming ==
AnonymousFunctionNamingPolicy.MAPPED) {
passes.add(nameMappedAnonymousFunctions);
}
// The mapped name anonymous function pass makes use of information that
// the extract prototype member declarations pass removes so the former
// happens before the latter.
//
// Extracting prototype properties screws up the heuristic renaming
// policies, so never run it when those policies are requested.
if (options.extractPrototypeMemberDeclarations &&
(options.propertyRenaming != PropertyRenamingPolicy.HEURISTIC &&
options.propertyRenaming !=
PropertyRenamingPolicy.AGGRESSIVE_HEURISTIC)) {
passes.add(extractPrototypeMemberDeclarations);
}
if (options.coalesceVariableNames) {
passes.add(coalesceVariableNames);
}
if (options.ambiguateProperties &&
(options.propertyRenaming == PropertyRenamingPolicy.ALL_UNQUOTED)) {
passes.add(ambiguateProperties);
}
if (options.propertyRenaming != PropertyRenamingPolicy.OFF) {
passes.add(renameProperties);
}
// Reserve global names added to the "windows" object.
if (options.reserveRawExports) {
passes.add(gatherRawExports);
}
// This comes after property renaming because quoted property names must
// not be renamed.
if (options.convertToDottedProperties) {
passes.add(convertToDottedProperties);
}
// Property renaming must happen before this pass runs since this
// pass may convert dotted properties into quoted properties. It
// is beneficial to run before alias strings, alias keywords and
// variable renaming.
if (options.rewriteFunctionExpressions) {
passes.add(rewriteFunctionExpressions);
}
// This comes after converting quoted property accesses to dotted property
// accesses in order to avoid aliasing property names.
if (!options.aliasableStrings.isEmpty() || options.aliasAllStrings) {
passes.add(aliasStrings);
}
if (options.aliasExternals) {
passes.add(aliasExternals);
}
if (options.aliasKeywords) {
passes.add(aliasKeywords);
}
if (options.collapseVariableDeclarations) {
passes.add(collapseVariableDeclarations);
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
}
passes.add(denormalize);
if (options.instrumentationTemplate != null) {
passes.add(instrumentFunctions);
}
if (options.variableRenaming != VariableRenamingPolicy.ALL) {
// If we're leaving some (or all) variables with their old names,
// then we need to undo any of the markers we added for distinguishing
// local variables ("$$1").
passes.add(invertContextualRenaming);
}
if (options.variableRenaming != VariableRenamingPolicy.OFF) {
passes.add(renameVars);
}
// This pass should run after names stop changing.
if (options.processObjectPropertyString) {
passes.add(objectPropertyStringPostprocess);
}
if (options.labelRenaming) {
passes.add(renameLabels);
}
if (options.anonymousFunctionNaming ==
AnonymousFunctionNamingPolicy.UNMAPPED) {
passes.add(nameUnmappedAnonymousFunctions);
}
// Safety check
if (options.checkSymbols) {
passes.add(sanityCheckVars);
}
return passes;
}
/** Creates the passes for the main optimization loop. */
private List<PassFactory> getMainOptimizationLoop() {
List<PassFactory> passes = Lists.newArrayList();
if (options.inlineGetters) {
passes.add(inlineGetters);
}
passes.addAll(getCodeRemovingPasses());
if (options.inlineFunctions || options.inlineLocalFunctions) {
passes.add(inlineFunctions);
}
if (options.removeUnusedVars) {
if (options.deadAssignmentElimination) {
passes.add(deadAssignmentsElimination);
}
passes.add(removeUnusedVars);
}
assertAllLoopablePasses(passes);
return passes;
}
/** Creates several passes aimed at removing code. */
private List<PassFactory> getCodeRemovingPasses() {
List<PassFactory> passes = Lists.newArrayList();
if (options.inlineVariables || options.inlineLocalVariables) {
passes.add(inlineVariables);
} else if (options.inlineConstantVars) {
passes.add(inlineConstants);
}
if (options.removeConstantExpressions) {
passes.add(removeConstantExpressions);
}
if
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> (options.foldConstants) {
// These used to be one pass.
passes.add(minimizeExitPoints);
passes.add(foldConstants);
}
if (options.removeDeadCode) {
passes.add(removeUnreachableCode);
}
if (options.removeUnusedPrototypeProperties) {
passes.add(removeUnusedPrototypeProperties);
}
assertAllLoopablePasses(passes);
return passes;
}
/**
* Checks for code that is probably wrong (such as stray expressions).
*/
// TODO(bolinfest): Write a CompilerPass for this.
final PassFactory suspiciousCode =
new PassFactory("suspiciousCode", true) {
@Override
protected CompilerPass createInternal(final AbstractCompiler compiler) {
List<Callback> sharedCallbacks = Lists.newArrayList();
sharedCallbacks.add(new CheckAccidentalSemicolon(CheckLevel.WARNING));
sharedCallbacks.add(new CheckSideEffects(CheckLevel.WARNING));
if (options.checkGlobalThisLevel.isOn()) {
sharedCallbacks.add(
new CheckGlobalThis(compiler, options.checkGlobalThisLevel));
}
return combineChecks(compiler, sharedCallbacks);
}
};
/** Verify that all the passes are one-time passes. */
private void assertAllOneTimePasses(List<PassFactory> passes) {
for (PassFactory pass : passes) {
Preconditions.checkState(pass.isOneTimePass());
}
}
/** Verify that all the passes are multi-run passes. */
private void assertAllLoopablePasses(List<PassFactory> passes) {
for (PassFactory pass : passes) {
Preconditions.checkState(!pass.isOneTimePass());
}
}
/** Checks for validity of the control structures. */
private final PassFactory checkControlStructures =
new PassFactory("checkControlStructures", true) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
return new ControlStructureCheck(compiler);
}
};
/** Checks that all constructed classes are goog.require()d. */
private final PassFactory checkRequires =
new PassFactory("checkRequires", true) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
return new CheckRequiresForConstructors(compiler, options.checkRequires
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>(AbstractCompiler compiler) {
return new GlobalTypeResolver(compiler);
}
};
/** Rusn type inference. */
private final PassFactory inferTypes =
new PassFactory("inferTypes", false) {
@Override
protected CompilerPass createInternal(final AbstractCompiler compiler) {
return new CompilerPass() {
@Override
public void process(Node externs, Node root) {
Preconditions.checkNotNull(topScope);
Preconditions.checkNotNull(typedScopeCreator);
makeTypeInference(compiler).process(externs, root);
}
};
}
};
/** Checks type usage */
private final PassFactory checkTypes =
new PassFactory("checkTypes", false) {
@Override
protected CompilerPass createInternal(final AbstractCompiler compiler) {
return new CompilerPass() {
@Override
public void process(Node externs, Node root) {
Preconditions.checkNotNull(topScope);
Preconditions.checkNotNull(typedScopeCreator);
TypeCheck check = makeTypeCheck(compiler);
check.process(externs, root);
compiler.getErrorManager().setTypedPercent(check.getTypedPercent());
}
};
}
};
/**
* Checks possible execution paths of the program for problems: missing return
* statements and dead code.
*/
private final PassFactory checkControlFlow =
new PassFactory("checkControlFlow", true) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
List<Callback> callbacks = Lists.newArrayList();
if (options.checkUnreachableCode.isOn()) {
callbacks.add(
new CheckUnreachableCode(compiler, options.checkUnreachableCode));
}
if (options.checkMissingReturn.isOn() && options.checkTypes) {
callbacks.add(
new CheckMissingReturn(compiler, options.checkMissingReturn));
}
return combineChecks(compiler, callbacks);
}
};
/** Checks access controls. Depends on type-inference. */
private final PassFactory checkAccessControls =
new PassFactory("checkAccessControls", true) {
@Override
protected CompilerPass createInternal(AbstractCompiler compiler) {
return new CheckAccessControls(compiler);
}
};
/** Executes the given callbacks with a {@link CombinedCompilerPass}. */
private static CompilerPass combineChecks(AbstractCompiler compiler,
List<Callback
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>/*
* Copyright 2004 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.javascript.rhino.Node;
/**
* Abstracted consumer of the CodeGenerator output.
*
* @see CodeGenerator
* @see CodePrinter
* @see InlineCostEstimator
*
*
*
*/
abstract class CodeConsumer {
boolean statementNeedsEnded = false;
boolean statementStarted = false;
boolean sawFunction = false;
/**
* Starts the source mapping for the given
* node at the current position.
*/
void startSourceMapping(Node node) {
}
/**
* Finishes the source mapping for the given
* node at the current position.
*/
void endSourceMapping(Node node) {
}
/**
* Generates the source map from the given code consumer,
* appending the information it saved to the SourceMap
* object given.
*/
void generateSourceMap(SourceMap map){
}
/**
* Returns the current length of the buffer in which
* the generated code is being placed.
*/
abstract int getCurrentBufferLength();
/**
* Returns the current character position on the current
* line in the generated code.
*/
abstract int getCurrentCharIndex();
/**
* Returns the current line in the generated code.
*/
abstract int getCurrentLineIndex();
/**
* Provides a means of interrupting the CodeGenerator. Derived classes should
* return false to stop further processing.
*/
boolean continueProcessing() {
return true;
}
/**
* Retrieve the last character of the last string sent to append.
*/
abstract char getLastChar();
void addIdentifier(String identifier) {
add
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>(identifier);
}
/**
* Appends a string to the code, keeping track of the current line length.
*
* NOTE: the string must be a complete token--partial strings or
* partial regexes will run the risk of being split across lines.
*
* Do not directly append newlines with this method. Instead use
* {@link #startNewLine}.
*/
abstract void append(String str);
void appendBlockStart() {
append("{");
}
void appendBlockEnd() {
append("}");
}
void startNewLine() {
}
void maybeLineBreak() {
maybeCutLine();
}
void maybeCutLine() {
}
void endLine() {
}
void notePreferredLineBreak() {
}
void beginBlock() {
if (statementNeedsEnded) {
append(";");
maybeLineBreak();
}
appendBlockStart();
endLine();
statementNeedsEnded = false;
}
void endBlock() {
endBlock(false);
}
void endBlock(boolean statementContext) {
appendBlockEnd();
if (statementContext) {
endLine();
}
statementNeedsEnded = false;
}
void listSeparator() {
add(",");
maybeLineBreak();
}
/**
* Indicates the end of a statement and a ';' may need to be added.
* But we don't add it now, in case we're at the end of a block (in which
* case we don't have to add the ';').
* See maybeEndStatement()
*/
void endStatement() {
endStatement(false);
}
void endStatement(boolean needSemiColon) {
if (needSemiColon) {
append(";");
maybeLineBreak();
statementNeedsEnded = false;
} else if (statementStarted) {
statementNeedsEnded = true;
}
}
/**
* This is to be called when we're in a statement. If the prev statement
* needs to be ended, add a ';'.
*/
void maybeEndStatement() {
// Add a ';' if we need to.
if (statementNeedsEnded) {
append(";");
maybeLineBreak();
endLine();
statementNeedsEnded = false;
}
statementStarted = true;
}
void endFunction() {
endFunction(false
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>);
}
void endFunction(boolean statementContext) {
sawFunction = true;
if (statementContext) {
endLine();
}
}
void beginCaseBody() {
append(":");
}
void endCaseBody() {
}
void add(String newcode) {
maybeEndStatement();
if (newcode.length() == 0) {
return;
}
char c = newcode.charAt(0);
if ((isWordChar(c) || c == '\\') &&
isWordChar(getLastChar())) {
// need space to separate. This is not pretty printing.
// For example: "return foo;"
append(" ");
}
append(newcode);
}
void appendOp(String op, boolean binOp) {
append(op);
}
void addOp(String op, boolean binOp) {
maybeEndStatement();
char first = op.charAt(0);
char prev = getLastChar();
if ((first == '+' || first == '-') && prev == first) {
// This is not pretty printing. This is to prevent misparsing of
// things like "x + ++y" or "x++ + ++y"
append(" ");
} else if (Character.isLetter(first) &&
isWordChar(prev)) {
// Make sure there is a space after e.g. instanceof , typeof
append(" ");
} else if (prev == '-' && first == '>') {
// Make sure that we don't emit -->
append(" ");
}
// Allow formating around the operator.
appendOp(op, binOp);
// Line breaking after an operator is always safe. Line breaking before an
// operator on the other hand is not. We only line break after a bin op
// because it looks strange.
if (binOp) {
maybeCutLine();
}
}
void addNumber(double x) {
// This is not pretty printing. This is to prevent misparsing of x- -4 as
// x--4 (which is a syntax error).
char prev = getLastChar();
if (x < 0 && prev == '-') {
add(" ");
}
if ((long) x == x) {
long value = (long) x;
long mantissa = value;
int exp =
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> 0;
if (x >= 100) {
while (mantissa / 10 * Math.pow(10, exp + 1) == value) {
mantissa /= 10;
exp++;
}
}
if (exp > 2) {
add(Long.toString(mantissa) + "E" + Integer.toString(exp));
} else {
add(Long.toString(value));
}
} else {
add(String.valueOf(x));
}
}
static boolean isWordChar(char ch) {
return (ch == '_' ||
ch == '$' ||
Character.isLetterOrDigit(ch));
}
/**
* If the body of a for loop or the then clause of an if statement has
* a single statement, should it be wrapped in a block? Doing so can
* help when pretty-printing the code, and permits putting a debugging
* breakpoint on the statement inside the condition.
*
* @return {@boolean true} if such expressions should be wrapped
*/
boolean shouldPreserveExtraBlocks() {
return false;
}
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> {
JSType newAlternate = alternate.resolve(t, scope);
changed |= (alternate != newAlternate);
resolvedTypes.add(alternate);
}
if (changed) {
Set<JSType> newAlternates = resolvedTypes.build();
Preconditions.checkState(newAlternates.hashCode() == this.hashcode);
alternates = newAlternates;
}
return this;
}
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> ZEROS_AFTER_54:
// x1.1 -> x1 + 1 (round up)
// x0.1 -> x0 (round down)
if (bit54 & bit53)
sum += 1.0;
sum *= factor;
break;
case MIXED_AFTER_54:
// x.100...1.. -> x + 1 (round up)
// x.0anything -> x (round down)
if (bit54)
sum += 1.0;
sum *= factor;
break;
}
}
/* We don't worry about inaccurate numbers for any other base. */
}
return sum;
}
public static String escapeString(String s)
{
return escapeString(s, '"');
}
/**
* For escaping strings printed by object and array literals; not quite
* the same as 'escape.'
*/
public static String escapeString(String s, char escapeQuote)
{
if (!(escapeQuote == '"' || escapeQuote == '\'')) Kit.codeBug();
StringBuffer sb = null;
for(int i = 0, L = s.length(); i != L; ++i) {
int c = s.charAt(i);
if (' ' <= c && c <= '~' && c != escapeQuote && c != '\\') {
// an ordinary print character (like C isprint()) and not "
// or \ .
if (sb != null) {
sb.append((char)c);
}
continue;
}
if (sb == null) {
sb = new StringBuffer(L + 3);
sb.append(s);
sb.setLength(i);
}
int escape = -1;
switch (c) {
case '\b': escape = 'b'; break;
case '\f': escape = 'f'; break;
case '\n': escape = 'n'; break;
case '\r': escape = 'r'; break;
case '\t': escape = 't'; break;
case 0xb: escape = 'v'; break; // Java lacks \v.
case ' ': escape = ' '; break;
case '\\': escape = '\\
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>'; break;
}
if (escape >= 0) {
// an \escaped sort of character
sb.append('\\');
sb.append((char)escape);
} else if (c == escapeQuote) {
sb.append('\\');
sb.append(escapeQuote);
} else {
int hexSize;
if (c < 256) {
// 2-digit hex
sb.append("\\x");
hexSize = 2;
} else {
// Unicode.
sb.append("\\u");
hexSize = 4;
}
// append hexadecimal form of c left-padded with 0
for (int shift = (hexSize - 1) * 4; shift >= 0; shift -= 4) {
int digit = 0xf & (c >> shift);
int hc = (digit < 10) ? '0' + digit : 'a' - 10 + digit;
sb.append((char)hc);
}
}
}
return (sb == null) ? s : sb.toString();
}
static boolean isValidIdentifierName(String s)
{
int L = s.length();
if (L == 0)
return false;
if (!Character.isJavaIdentifierStart(s.charAt(0)))
return false;
for (int i = 1; i != L; ++i) {
if (!Character.isJavaIdentifierPart(s.charAt(i)))
return false;
}
return !TokenStream.isKeyword(s);
}
/**
* Convert the value to a string.
*
* See ECMA 9.8.
*/
public static String toString(Object val) {
for (;;) {
if (val == null) {
return "null";
}
if (val instanceof String) {
return (String)val;
}
if (val instanceof Number) {
// XXX should we just teach NativeNumber.stringValue()
// about Numbers?
return numberToString(((Number)val).doubleValue(), 10);
}
return val.toString();
}
}
public static String numberToString(double d, int base) {
if (d != d)
return "NaN";
if (d == Double.POSITIVE_INFINITY)
return "Infinity
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>";
if (d == Double.NEGATIVE_INFINITY)
return "-Infinity";
if (d == 0.0)
return "0";
if ((base < 2) || (base > 36)) {
throw Context.reportRuntimeError1(
"msg.bad.radix", Integer.toString(base));
}
if (base != 10) {
return DToA.JS_dtobasestr(base, d);
} else {
StringBuffer result = new StringBuffer();
DToA.JS_dtostr(result, DToA.DTOSTR_STANDARD, 0, d);
return result.toString();
}
}
/**
* If str is a decimal presentation of Uint32 value, return it as long.
* Othewise return -1L;
*/
public static long testUint32String(String str)
{
// The length of the decimal string representation of
// UINT32_MAX_VALUE, 4294967296
final int MAX_VALUE_LENGTH = 10;
int len = str.length();
if (1 <= len && len <= MAX_VALUE_LENGTH) {
int c = str.charAt(0);
c -= '0';
if (c == 0) {
// Note that 00,01 etc. are not valid Uint32 presentations
return (len == 1) ? 0L : -1L;
}
if (1 <= c && c <= 9) {
long v = c;
for (int i = 1; i != len; ++i) {
c = str.charAt(i) - '0';
if (!(0 <= c && c <= 9)) {
return -1;
}
v = 10 * v + c;
}
// Check for overflow
if ((v >>> 32) == 0) {
return v;
}
}
}
return -1;
}
static boolean isSpecialProperty(String s)
{
return s.equals("__proto__") || s.equals("__parent__");
}
// ------------------
// Statements
// ------------------
public static String getMessage0(String messageId)
{
return getMessage(messageId, null);
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
/**
* An abstract representation of a JavaScript source file, as input to
* JSCompiler.
*
* @author nicksantos@google.com (Nick Santos)
*
*/
public class JSSourceFile extends SourceFile {
public static JSSourceFile fromFile(String fileName, Charset charSet) {
return new JSSourceFile(SourceFile.fromFile(fileName, charSet));
}
public static JSSourceFile fromFile(String fileName) {
return new JSSourceFile(SourceFile.fromFile(fileName, Charsets.UTF_8));
}
public static JSSourceFile fromFile(File file, Charset charSet) {
return new JSSourceFile(SourceFile.fromFile(file, charSet));
}
public static JSSourceFile fromFile(File file) {
return new JSSourceFile(SourceFile.fromFile(file, Charsets.UTF_8));
}
public static JSSourceFile fromCode(String fileName, String code) {
return new JSSourceFile(SourceFile.fromCode(fileName, code));
}
public static JSSourceFile fromInputStream(String fileName, InputStream s)
throws IOException {
return new JSSourceFile(SourceFile.fromInputStream(fileName, s));
}
public static JSSourceFile fromGenerator(String
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>codingConvention = compiler.getCodingConvention();
this.types = Lists.newArrayList();
}
public void visit(NodeTraversal t, Node n, Node parent) {
switch (n.getType()) {
case Token.CALL:
String className = findRequire
? codingConvention.extractClassNameIfRequire(n, parent)
: codingConvention.extractClassNameIfProvide(n, parent);
if (className != null) {
types.add(className);
}
break;
}
}
}
/**
* Gets the source line for the indicated line number.
*
* @param lineNumber the line number, 1 being the first line of the file.
* @return The line indicated. Does not include the newline at the end
* of the file. Returns {@code null} if it does not exist,
* or if there was an IO exception.
*/
public String getLine(int lineNumber) {
return getSourceFile().getLine(lineNumber);
}
/**
* Get a region around the indicated line number. The exact definition of a
* region is implementation specific, but it must contain the line indicated
* by the line number. A region must not start or end by a carriage return.
*
* @param lineNumber the line number, 1 being the first line of the file.
* @return The line indicated. Returns {@code null} if it does not exist,
* or if there was an IO exception.
*/
public Region getRegion(int lineNumber) {
return getSourceFile().getRegion(lineNumber);
}
public String getCode() throws IOException {
return getSourceFile().getCode();
}
/** Returns the module to which the input belongs. */
public JSModule getModule() {
return module;
}
/** Sets the module to which the input belongs. */
public void setModule(JSModule module) {
// An input may only belong to one module.
Preconditions.checkArgument(
module == null || this.module == null || this.module == module);
this.module = module;
}
public boolean isExtern() {
return isExtern;
}
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> Default clock that calls through to the system clock. Can be overridden
* in unit tests.
*/
static InternalClock clock = new InternalClock() {
public long currentTimeMillis() {
return System.currentTimeMillis();
}
};
/**
* Create and start a tracer.
* Both type and comment may be null. See class comment for usage.
*
* @param type The type for totalling
* @param comment Comment about this tracer
*/
Tracer(@Nullable String type, @Nullable String comment) {
this.type = type;
this.comment = comment == null ? "" : comment;
startTimeMs = clock.currentTimeMillis();
startThread = Thread.currentThread();
if (!extraTracingStatistics.isEmpty()) {
int size = extraTracingStatistics.size();
extraTracingValues = new long[size];
int i = 0;
for (TracingStatistic tracingStatistic : extraTracingStatistics) {
extraTracingValues[i] = tracingStatistic.start(startThread);
i++;
}
}
ThreadTrace trace = getThreadTrace();
// Do nothing if the current thread trace wasn't initialized.
if (!trace.isInitialized()) {
return;
}
// Check if we are creating too many Tracers.
if (trace.events.size() >= MAX_TRACE_SIZE) {
logger.log(Level.WARNING,
"Giant thread trace. Too many Tracers created. "
+ "Clearing to avoid memory leak.",
new Throwable(trace.toString()));
trace.truncateEvents();
}
// Check if we forgot to close the Tracers.
if (trace.outstandingEvents.size() >= MAX_TRACE_SIZE) {
logger.log(Level.WARNING,
"Too many outstanding Tracers. Tracer.stop() is missing "
+ "or Tracer.stop() is not wrapped in a "
+ "try/finally block. "
+ "Clearing to avoid memory leak.",
new Throwable(trace.toString()));
trace.truncateOutstandingEvents();
}
trace.startEvent(this);
}
/**
* Create a tracer that isn't summed as part of a total
*
* @param comment Comment about this tracer
*/
Tracer(String comment) {
this(null, comment);
}
/**
*
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> Construct a tracer whose type is based on the short name of the object
* @param object Object to use as type name
* @param comment A comment
* @return new Tracer.
*/
static Tracer shortName(Object object, String comment) {
if (object == null) {
return new Tracer(comment);
}
return new Tracer(object.getClass().getSimpleName(), comment);
}
/**
* Converts 'v' to a string and pads it with up to 16 spaces for
* improved alignment.
* @param v The value to convert.
* @param digits_column_width The desired with of the string.
*/
private static String longToPaddedString(long v, int digits_column_width) {
int digit_width = numDigits(v);
StringBuilder sb = new StringBuilder();
appendSpaces(sb, digits_column_width - digit_width);
sb.append(v);
return sb.toString();
}
/**
* Gets the number of digits in an integer when printed in base 10. Assumes
* a positive integer.
* @param n The value.
* @return The number of digits in the string.
*/
private static int numDigits(long n) {
int i = 0;
do {
i++;
n = n / 10;
} while (n > 0);
return i;
}
/**
* Gets a string of spaces of the length specified.
* @param sb The string builder to append to.
* @param numSpaces The number of spaces in the string.
*/
@VisibleForTesting
static void appendSpaces(StringBuilder sb, int numSpaces) {
if (numSpaces > 16) {
logger.warning("Tracer.appendSpaces called with large numSpaces");
// Avoid long loop in case some bug in the caller
numSpaces = 16;
}
while (numSpaces >= 5) {
sb.append(" ");
numSpaces -= 5;
}
// We know it's less than 5 now
switch (numSpaces) {
case 1:
sb.append(" ");
break;
case 2:
sb.append(" ");
break;
case 3:
sb.append("
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> ");
break;
case 4:
sb.append(" ");
break;
}
}
/**
* Adds a new tracing statistic to a trace
*
* @param tracingStatistic to enable a run
* @return The index of this statistic (for use with stat.extraInfo()), or
* -1 if the statistic is not enabled.
*/
static int addTracingStatistic(TracingStatistic tracingStatistic) {
// Check to see if we can enable the tracing statistic before actually
// adding it.
if (tracingStatistic.enable()) {
// No synchronization needed, since this is a copy-on-write array.
extraTracingStatistics.add(tracingStatistic);
// 99.9% of the time, this will be O(1) and return extraTracingStatistics.length - 1
return extraTracingStatistics.lastIndexOf(tracingStatistic);
} else {
return -1;
}
}
/**
* For testing purposes only. These removes all current tracers. Severe errors can occur
* if there are any active tracers going on when this is called.
*
* The test suite uses this to remove any tracers that it has added.
*/
@VisibleForTesting
static void clearTracingStatisticsTestingOnly() {
extraTracingStatistics.clear();
}
/**
* Stop the trace.
* This may only be done once and must be done from the same thread
* that started it.
* @param silence_threshold Traces for time less than silence_threshold
* ms will be left out of the trace report. A value of -1 indicates
* that the current ThreadTrace silence_threshold should be used.
* @return The time that this trace actually ran
*/
long stop(int silence_threshold) {
Preconditions.checkState(Thread.currentThread() == startThread);
ThreadTrace trace = getThreadTrace();
// Do nothing if the thread trace was not initialized.
if (!trace.isInitialized()) {
return 0;
}
stopTimeMs = clock.currentTimeMillis();
if (extraTracingValues != null) {
// We use extraTracingValues.length rather than extraTracingStatistics.size() because
// a new statistic may have been added
for (int i = 0; i < extraTracingValues.length; i++) {
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> long value = extraTracingStatistics.get(i).stop(startThread);
extraTracingValues[i] = value - extraTracingValues[i];
}
}
// Do nothing if the thread trace was not initialized.
if (!trace.isInitialized()) {
return 0;
}
trace.endEvent(this, silence_threshold);
return stopTimeMs - startTimeMs;
}
/** Stop the trace using the default silence_threshold
*
* @return The time that this trace actually ran.
*/
long stop() {
return stop(-1);
}
@Override public String toString() {
if (type == null) {
return comment;
} else {
return "[" + type + "] " + comment;
}
}
static void setDefaultSilenceThreshold(int threshold) {
getThreadTrace().defaultSilenceThreshold = threshold;
}
/**
* Initialize the trace associated with the current thread by clearing
* out any existing trace. There shouldn't be a trace so if one is
* found we log it as an error.
*/
static void initCurrentThreadTrace() {
ThreadTrace events = getThreadTrace();
if (!events.isEmpty()) {
logger.log(Level.WARNING,
"Non-empty timer log:\n" + events,
new Throwable());
clearThreadTrace();
// Grab a new thread trace if we find a previous non-empty ThreadTrace.
events = getThreadTrace();
}
// Mark the thread trace as initialized.
events.init();
}
static void initCurrentThreadTrace(int default_silence_threshold) {
initCurrentThreadTrace();
setDefaultSilenceThreshold(default_silence_threshold);
}
/**
* Returns a timer report similar to the one described in the class comment.
*
* @return The timer report as a string
*/
static String getCurrentThreadTraceReport() {
return getThreadTrace().toString();
}
/**
* Logs a timer report similar to the one described in the class comment.
*/
static void logCurrentThreadTrace() {
ThreadTrace trace = getThreadTrace();
// New threads must call Tracer.initCurrentThreadTrace() before Tracer
// statistics are gathered. This is a recent change (Jun 2007) that
// prevents spurious Third
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>0:06:11.566", "11.566") */
private static String formatTime(long time) {
int sec = (int) ((time / 1000) % 60);
int ms = (int) (time % 1000);
return String.format("%02d.%03d", sec, ms);
}
/** An event is created every time a Tracer is created or stopped */
private static final class Event {
boolean isStart; // else is_stop
Tracer tracer;
Event(boolean start, Tracer t) {
isStart = start;
tracer = t;
}
long eventTime() {
return isStart ? tracer.startTimeMs : tracer.stopTimeMs;
}
/**
* Converts the event to a formatted string.
* @param prevEventTime The time of the previous event which appears at
* the left most part of the trace line.
* @param indent The indentation to put before the tracer to show the
* hieararchy.
* @param digitsColWidth How many characters the digits should use.
* @return The formatted string.
*/
String toString(long prevEventTime, String indent, int digitsColWidth) {
StringBuilder sb = new StringBuilder(120);
if (prevEventTime == -1) {
appendSpaces(sb, digitsColWidth);
} else {
sb.append(longToPaddedString(eventTime() - prevEventTime, digitsColWidth));
}
sb.append(' ');
sb.append(formatTime(eventTime()));
if (isStart) {
sb.append(" Start ");
appendSpaces(sb, digitsColWidth);
sb.append(" ");
} else {
sb.append(" Done ");
long delta = tracer.stopTimeMs - tracer.startTimeMs;
sb.append(longToPaddedString(delta, digitsColWidth));
sb.append(" ms ");
if (tracer.extraTracingValues != null) {
for (int i = 0; i < tracer.extraTracingValues.length; i++) {
delta = tracer.extraTracingValues[i];
sb.append(String.format("%4d", delta));
sb.append(extraTracing
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>Statistics.get(i).getUnits());
sb.append("; ");
}
}
}
sb.append(indent);
sb.append(tracer.toString());
return sb.toString();
}
}
/** Stores a thread's Trace */
static final class ThreadTrace {
/** Events taking less than this number of milliseconds are not reported. */
int defaultSilenceThreshold; // non-final
/** The Events corresponding to each startEvent/stopEvent */
final ArrayList<Event> events = new ArrayList<Event>();
/** Tracers that have not had their .stop() called */
final HashSet<Tracer> outstandingEvents = new HashSet<Tracer>();
/** Map from type to Stat object */
final Map<String, Stat> stats = new HashMap<String, Stat>();
/**
* True if {@code outstandingEvents} has been cleared because we exceeded
* the max trace limit.
*/
boolean isOutstandingEventsTruncated = false;
/**
* True if {@code events} has been cleared because we exceeded the max
* trace limit.
*/
boolean isEventsTruncated = false;
/**
* Set to true if {@link Tracer#initCurrentThreadTrace()} was called by
* the current thread.
*/
boolean isInitialized = false;
/**
* Whether pretty printing is enabled for the trace.
*/
boolean prettyPrint = false;
/** Initialize the trace. */
void init() {
isInitialized = true;
}
/** Is initialized? */
boolean isInitialized() {
return isInitialized;
}
/**
* Called by the constructor {@link Tracer#Tracer(String, String)} to create
* a start event.
*/
void startEvent(Tracer t) {
events.add(new Event(true, t));
boolean notAlreadyOutstanding = outstandingEvents.add(t);
Preconditions.checkState(notAlreadyOutstanding);
}
/**
* Called by {@link Tracer#stop()} to create a stop event.
*/
void endEvent(Tracer t, int silenceThreshold) {
boolean wasOutstanding = outstandingEvents.remove(t);
if (!wasOutstanding) {
if (isOutstandingEventsTruncated) {
// The events stack overflowed and was truncated, so just log a
// warning. Otherwise, we get an exception which is extremely
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> // confusing.
logger.log(Level.WARNING,
"event not found, probably because the event stack "
+ "overflowed and was truncated",
new Throwable());
} else {
// throw an exception if the event was not found and the events stack
// is pristine
throw new IllegalStateException();
}
}
long elapsed = t.stopTimeMs - t.startTimeMs;
if (silenceThreshold == -1) { // use default
silenceThreshold = defaultSilenceThreshold;
}
if (elapsed < silenceThreshold) {
// If this one is silent then we need to remove the start Event
boolean removed = false;
for (int i = 0; i < events.size(); i++) {
Event e = events.get(i);
if (e.tracer == t) {
Preconditions.checkState(e.isStart);
events.remove(i);
removed = true;
break;
}
}
// Only assert if we didn't find the original and the events
// weren't truncated.
Preconditions.checkState(removed || isEventsTruncated);
} else {
events.add(new Event(false, t));
}
if (t.type != null) {
Stat stat = stats.get(t.type);
if (stat == null) {
stat = new Stat();
if (!extraTracingStatistics.isEmpty()) {
stat.extraInfo = new int[extraTracingStatistics.size()];
}
stats.put(t.type, stat);
}
stat.count++;
if (typeToCountMap != null) {
typeToCountMap.incrementBy(t.type, 1);
}
stat.clockTime += elapsed;
if (typeToTimeMap != null) {
typeToTimeMap.incrementBy(t.type, elapsed);
}
if (stat.extraInfo != null && t.extraTracingValues != null) {
int overlapLength = Math.min(stat.extraInfo.length, t.extraTracingValues.length);
for (int i = 0; i < overlapLength; i++) {
stat.extraInfo[i] += t.extraTracingValues[i];
AtomicTracerStatMap map = extraTracingStatistics.get(i).getTracingStat();
if (map !=
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> null) {
map.incrementBy(t.type, t.extraTracingValues[i]);
}
}
}
if (elapsed < silenceThreshold) {
stat.silent++;
if (typeToSilentMap != null) {
typeToSilentMap.incrementBy(t.type, 1);
}
}
}
}
boolean isEmpty() {
return events.size() == 0 && outstandingEvents.size() == 0;
}
void truncateOutstandingEvents() {
isOutstandingEventsTruncated = true;
outstandingEvents.clear();
}
void truncateEvents() {
isEventsTruncated = true;
events.clear();
}
/** Produces the lovely Trace seen in the class comments */
// Nullness checker does not understand that prettyPrint => indent != null
@SuppressWarnings("nullness")
@Override public String toString() {
int numDigits = getMaxDigits();
StringBuilder sb = new StringBuilder();
long etime = -1;
LinkedList<String> indent = prettyPrint ? new LinkedList<String>() : null;
for (Event e : events) {
if (prettyPrint && !e.isStart && !indent.isEmpty()) {
indent.pop();
}
sb.append(" ");
if (prettyPrint) {
sb.append(e.toString(etime, Joiner.on("").join(indent), numDigits));
} else {
sb.append(e.toString(etime, "", 4));
}
etime = e.eventTime();
sb.append('\n');
if (prettyPrint && e.isStart) {
indent.push("| ");
}
}
if (outstandingEvents.size() != 0) {
long now = clock.currentTimeMillis();
sb.append(" Unstopped timers:\n");
for (Tracer t : outstandingEvents) {
sb.append(" ").
append(t).
append(" (").
append(now - t.startTimeMs).
append(" ms, started at ").
append(formatTime(t.startTimeMs)).
append(")\n");
}
}
for (String key : stats.keySet()) {
Stat stat = stats.get(key);
if (stat.count > 1) {
sb.append(" TOTAL ").
append(
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>key).
append(" ").
append(stat.count).
append(" (").
append(stat.clockTime).
append(" ms");
if (stat.extraInfo != null) {
for (int i = 0; i < stat.extraInfo.length; i++) {
sb.append("; ");
sb.append(stat.extraInfo[i]).
append(' ').
append(extraTracingStatistics.get(i).getUnits());
}
}
sb.append(")\n");
}
}
return sb.toString();
}
/**
* Gets the maximum number of digits that can appear in the tracer output
* in the gaps between tracers or the duration of a tracer. This is used
* by the pretty printing case so that all of the tracers are aligned.
*/
private int getMaxDigits() {
long etime = -1;
long max_time = 0;
for (Event e : events) {
if (etime != -1) {
long time = e.eventTime() - etime;
max_time = Math.max(max_time, time);
}
if (!e.isStart) {
long time = e.tracer.stopTimeMs - e.tracer.startTimeMs;
max_time = Math.max(max_time, time);
}
etime = e.eventTime();
}
// Minimum is 3 to preserve an indent even when max is small.
return Math.max(3, numDigits(max_time));
}
}
/** Holds the ThreadTrace for each thread. */
private static ThreadLocal<ThreadTrace> traces = new ThreadLocal<ThreadTrace>();
/**
* Get the ThreadTrace for the current thread, creating one if necessary.
*/
static ThreadTrace getThreadTrace() {
ThreadTrace t = traces.get();
if (t == null) {
t = new ThreadTrace();
t.prettyPrint = defaultPrettyPrint;
traces.set(t);
}
return t;
}
/** Remove any ThreadTrace associated with the current thread */
static void clearThreadTrace() {
traces.set(null);
}
/**
* A TracingStatistic allows the program to add additional optional statistics to the trace
* output.
*
* The
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> path through
// the code identical to how it's been for years.
this.outputCharsetEncoder = null;
} else {
this.outputCharsetEncoder = outputCharset.newEncoder();
}
}
CodeGenerator(CodeConsumer consumer, Charset outputCharset) {
this(consumer, outputCharset, true);
}
CodeGenerator(CodeConsumer consumer) {
this(consumer, null, false);
}
void add(String str) {
cc.add(str);
}
private void addIdentifier(String identifier) {
cc.addIdentifier(identifierEscape(identifier));
}
void add(Node n) {
add(n, Context.OTHER);
}
void add(Node n, Context context) {
if (!cc.continueProcessing()) {
return;
}
int type = n.getType();
String opstr = NodeUtil.opToStr(type);
int childCount = n.getChildCount();
Node first = n.getFirstChild();
Node last = n.getLastChild();
// Handle all binary operators
if (opstr != null && first != last) {
Preconditions.checkState(childCount == 2);
int p = NodeUtil.precedence(type);
addLeftExpr(first, p, context);
cc.addOp(opstr, true);
// For right-hand-side of operations, only pass context if it's
// the IN_FOR_INIT_CLAUSE one.
Context rhsContext = getContextForNoInOperator(context);
// Handle associativity.
// e.g. if the parse tree is a * (b * c),
// we can simply generate a * b * c.
if (last.getType() == type &&
NodeUtil.isAssociative(type)) {
addExpr(last, p, rhsContext);
} else if (NodeUtil.isAssignmentOp(n) && NodeUtil.isAssignmentOp(last)) {
// Assignments are the only right-associative binary operators
addExpr(last, p, rhsContext);
} else {
addExpr(last, p + 1, rhsContext);
}
return;
}
cc.startSourceMapping(n);
switch (type) {
case Token.TRY: {
Preconditions.checkState(first.getNext().getType() ==
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> Token.BLOCK &&
first.getNext().getChildCount() <= 1);
Preconditions.checkState(childCount >= 2 && childCount <= 3);
add("try");
add(first, Context.PRESERVE_BLOCK);
// second child contains the catch block, or nothing if there
// isn't a catch block
Node catchblock = first.getNext().getFirstChild();
if (catchblock != null) {
add(catchblock);
}
if (childCount == 3) {
add("finally");
add(last, Context.PRESERVE_BLOCK);
}
break;
}
case Token.CATCH:
Preconditions.checkState(childCount == 3);
if (first.getNext().getType() != Token.EMPTY) {
throw new Error("Catch conditions not suppored because I think" +
" that it may be a netscape only feature.");
}
add("catch(");
add(first);
add(")");
add(last, Context.PRESERVE_BLOCK);
break;
case Token.THROW:
Preconditions.checkState(childCount == 1);
add("throw");
add(first);
// Must have a ';' after a throw statement, otherwise safari can't
// parse this.
cc.endStatement(true);
break;
case Token.RETURN:
add("return");
if (childCount == 1) {
add(first);
} else {
Preconditions.checkState(childCount == 0);
}
cc.endStatement();
break;
case Token.VAR:
if (first != null) {
add("var ");
addList(first, false, getContextForNoInOperator(context));
}
break;
case Token.NAME:
if (first == null || first.getType() == Token.EMPTY) {
addIdentifier(n.getString());
} else {
Preconditions.checkState(childCount == 1);
addIdentifier(n.getString());
cc.addOp("=", true);
if (first.getType() == Token.COMMA) {
addExpr(first, NodeUtil.precedence(Token.ASSIGN));
} else {
// Add expression, consider nearby code at lowest level of
// precedence.
addExpr(first, 0, getContextForNoInOperator
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>(context));
}
}
break;
case Token.ARRAYLIT:
add("[");
addList(first, (int[]) n.getProp(Node.SKIP_INDEXES_PROP));
add("]");
break;
case Token.LP:
add("(");
addList(first);
add(")");
break;
case Token.COMMA:
addList(first, false, context);
break;
case Token.NUMBER:
Preconditions.checkState(childCount == 0);
cc.addNumber(n.getDouble());
break;
case Token.TYPEOF:
case Token.VOID:
case Token.NOT:
case Token.BITNOT:
case Token.POS:
case Token.NEG: {
// All of these unary operators are right-associative
Preconditions.checkState(childCount == 1);
cc.addOp(NodeUtil.opToStrNoFail(type), false);
addExpr(first, NodeUtil.precedence(type));
break;
}
case Token.HOOK: {
Preconditions.checkState(childCount == 3);
int p = NodeUtil.precedence(type);
addLeftExpr(first, p + 1, context);
cc.addOp("?", true);
addExpr(first.getNext(), p);
cc.addOp(":", true);
addExpr(last, p);
break;
}
case Token.REGEXP:
if (first.getType() != Token.STRING ||
last.getType() != Token.STRING) {
throw new Error("Expected children to be strings");
}
String regexp = regexpEscape(first.getString(), outputCharsetEncoder);
// I only use one .add because whitespace matters
if (childCount == 2) {
add(regexp + last.getString());
} else {
Preconditions.checkState(childCount == 1);
add(regexp);
}
break;
case Token.GET_REF:
add(first);
break;
case Token.REF_SPECIAL:
Preconditions.checkState(childCount == 1);
add(first);
add(".");
add((String) n.getProp(Node.NAME_PROP));
break;
case Token.FUNCTION:
Preconditions.checkState(childCount == 3);
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> boolean funcNeedsParens = (context == Context.START_OF_EXPR);
if (funcNeedsParens) {
add("(");
}
add("function");
add(first);
add(first.getNext());
add(last, Context.PRESERVE_BLOCK);
cc.endFunction(context == Context.STATEMENT);
if (funcNeedsParens) {
add(")");
}
break;
case Token.SCRIPT:
case Token.BLOCK: {
boolean stripBlock = n.isSyntheticBlock() ||
((context != Context.PRESERVE_BLOCK) && (n.getChildCount() < 2));
if (!stripBlock) {
cc.beginBlock();
}
for (Node c = first; c != null; c = c.getNext()) {
add(c, Context.STATEMENT);
// VAR doesn't include ';' since it gets used in expressions
if (c.getType() == Token.VAR) {
cc.endStatement();
}
if (c.getType() == Token.FUNCTION) {
cc.maybeLineBreak();
}
// Prefer to break lines in between top-level statements
// because top level statements are more homogeneous.
if (type == Token.SCRIPT) {
cc.notePreferredLineBreak();
}
}
if (!stripBlock) {
cc.endBlock(context == Context.STATEMENT);
}
break;
}
case Token.FOR:
if (childCount == 4) {
add("for(");
if (first.getType() == Token.VAR) {
add(first, Context.IN_FOR_INIT_CLAUSE);
} else {
addExpr(first, 0, Context.IN_FOR_INIT_CLAUSE);
}
add(";");
add(first.getNext());
add(";");
add(first.getNext().getNext());
add(")");
addNonEmptyExpression(
last, getContextForNonEmptyExpression(context), false);
} else {
Preconditions.checkState(childCount == 3);
add("for(");
add(first);
add("in");
add(first.getNext());
add(")");
addNonEmptyExpression(
last, getContextForNonEmptyExpression(context), false);
}
break
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>;
case Token.DO:
Preconditions.checkState(childCount == 2);
add("do");
addNonEmptyExpression(first, Context.OTHER, false);
add("while(");
add(last);
add(")");
cc.endStatement();
break;
case Token.WHILE:
Preconditions.checkState(childCount == 2);
add("while(");
add(first);
add(")");
addNonEmptyExpression(
last, getContextForNonEmptyExpression(context), false);
break;
case Token.EMPTY:
Preconditions.checkState(childCount == 0);
break;
case Token.GETPROP: {
Preconditions.checkState(childCount == 2);
Preconditions.checkState(last.getType() == Token.STRING);
boolean needsParens = (first.getType() == Token.NUMBER);
if (needsParens) {
add("(");
}
addLeftExpr(first, NodeUtil.precedence(type), context);
if (needsParens) {
add(")");
}
add(".");
addIdentifier(last.getString());
break;
}
case Token.GETELEM:
Preconditions.checkState(childCount == 2);
addLeftExpr(first, NodeUtil.precedence(type), context);
add("[");
add(first.getNext());
add("]");
break;
case Token.WITH:
Preconditions.checkState(childCount == 2);
add("with(");
add(first);
add(")");
addNonEmptyExpression(
last, getContextForNonEmptyExpression(context), false);
break;
case Token.INC:
case Token.DEC: {
Preconditions.checkState(childCount == 1);
String o = type == Token.INC ? "++" : "--";
int postProp = n.getIntProp(Node.INCRDECR_PROP, 0);
// A non-zero post-prop value indicates a post inc/dec, default of zero
// is a pre-inc/dec.
if (postProp != 0) {
addLeftExpr(first, NodeUtil.precedence(type), context);
cc.addOp(o, false);
} else {
cc.addOp(o, false);
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
add(first);
}
break;
}
case Token.CALL:
// If the left hand side of the call is a direct reference to eval,
// then it must have a DIRECT_EVAL annotation. If it does not, then
// that means it was originally an indirect call to eval, and that
// indirectness must be preserved.
if (first.getType() == Token.NAME &&
"eval".equals(first.getString()) &&
!first.getBooleanProp(Node.DIRECT_EVAL)) {
add("(0,eval)");
} else {
addLeftExpr(first, NodeUtil.precedence(type), context);
}
add("(");
addList(first.getNext());
add(")");
break;
case Token.IF:
boolean hasElse = childCount == 3;
boolean ambiguousElseClause =
context == Context.BEFORE_DANGLING_ELSE && !hasElse;
if (ambiguousElseClause) {
cc.beginBlock();
}
add("if(");
add(first);
add(")");
if (hasElse) {
addNonEmptyExpression(
first.getNext(), Context.BEFORE_DANGLING_ELSE, false);
add("else");
addNonEmptyExpression(
last, getContextForNonEmptyExpression(context), false);
} else {
addNonEmptyExpression(first.getNext(), Context.OTHER, false);
Preconditions.checkState(childCount == 2);
}
if (ambiguousElseClause) {
cc.endBlock();
}
break;
case Token.NULL:
case Token.THIS:
case Token.FALSE:
case Token.TRUE:
Preconditions.checkState(childCount == 0);
add(Node.tokenToName(type));
break;
case Token.CONTINUE:
Preconditions.checkState(childCount <= 1);
add("continue");
if (childCount == 1) {
add(" ");
add(first);
}
cc.endStatement();
break;
case Token.DEBUGGER:
Preconditions.checkState(childCount == 0);
add("debugger");
cc.endStatement();
break;
case Token.BREAK:
Preconditions.checkState(childCount <= 1);
add("break");
if (childCount
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> == 1) {
add(" ");
add(first);
}
cc.endStatement();
break;
case Token.EXPR_VOID:
case Token.EXPR_RESULT:
if (type == Token.EXPR_VOID && validation) {
throw new Error("Unexpected EXPR_VOID. Should be EXPR_RESULT.");
}
Preconditions.checkState(childCount == 1);
add(first, Context.START_OF_EXPR);
cc.endStatement();
break;
case Token.NEW:
add("new ");
int precedence = NodeUtil.precedence(type);
// If the first child contains a CALL, then claim higher precedence
// to force parens. Otherwise, when parsed, NEW will bind to the
// first viable parens
if (NodeUtil.containsCall(first)) {
precedence = NodeUtil.precedence(first.getType()) + 1;
}
addExpr(first, precedence);
// '()' is optional when no arguments are present
Node next = first.getNext();
if (next != null) {
add("(");
addList(next);
add(")");
}
break;
case Token.STRING:
Preconditions.checkState(childCount == 0);
add(jsString(n.getString(), outputCharsetEncoder));
break;
case Token.DELPROP:
Preconditions.checkState(childCount == 1);
add("delete ");
add(first);
break;
case Token.OBJECTLIT: {
Preconditions.checkState(childCount % 2 == 0);
boolean needsParens = (context == Context.START_OF_EXPR);
if (needsParens) {
add("(");
}
add("{");
for (Node c = first; c != null; c = c.getNext().getNext()) {
if (c != first) {
cc.listSeparator();
}
// Object literal property names don't have to be quoted if they are
// not JavaScript keywords
if (c.getType() == Token.STRING &&
!TokenStream.isKeyword(c.getString()) &&
TokenStream.isJSIdentifier(c.getString()) &&
// do not encode literally any non-literal characters that were
// unicode escaped.
NodeUtil.isLatin(c.getString()))
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> {
add(c.getString());
} else {
addExpr(c, 1);
}
add(":");
addExpr(c.getNext(), 1);
}
add("}");
if (needsParens) {
add(")");
}
break;
}
case Token.SWITCH:
add("switch(");
add(first);
add(")");
cc.beginBlock();
addAllSiblings(first.getNext());
cc.endBlock(context == Context.STATEMENT);
break;
case Token.CASE:
Preconditions.checkState(childCount == 2);
add("case ");
add(first);
addCaseBody(last);
break;
case Token.DEFAULT:
Preconditions.checkState(childCount == 1);
add("default");
addCaseBody(first);
break;
case Token.LABEL:
Preconditions.checkState(childCount == 2);
add(first);
add(":");
addNonEmptyExpression(
last, getContextForNonEmptyExpression(context), true);
break;
// This node is auto generated in anonymous functions and should just get
// ignored for our purposes.
case Token.SETNAME:
break;
default:
throw new Error("Unknown type " + type + "\n" + n.toStringTree());
}
cc.endSourceMapping(n);
}
/**
* Adds a block or expression, substituting a VOID with an empty statement.
* This is used for "for (...);" and "if (...);" type statements.
*
* @param n The node to print.
* @param context The context to determine how the node should be printed.
*/
private void addNonEmptyExpression(
Node n, Context context, boolean allowNonBlockChild) {
Node nodeToProcess = n;
if (!allowNonBlockChild && n.getType() != Token.BLOCK) {
if (validation) {
throw new Error("Missing BLOCK child.");
}
}
// Strip unneeded blocks, that is blocks with <2 children unless
// the CodePrinter specifically wants to keep them.
if (n.getType() == Token.BLOCK ) {
int count = getNonEmptyChildCount(n);
if (count == 0) {
cc.endStatement(true);
return;
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
}
if (count == 1) {
// Hack around a couple of browser bugs:
// Safari needs a block around function declarations.
// IE6/7 needs a block around DOs.
Node firstAndOnlyChild = getFirstNonEmptyChild(n);
boolean alwaysWrapInBlock = cc.shouldPreserveExtraBlocks();
if (alwaysWrapInBlock ||
firstAndOnlyChild.getType() == Token.FUNCTION ||
firstAndOnlyChild.getType() == Token.DO) {
cc.beginBlock();
add(firstAndOnlyChild, Context.STATEMENT);
cc.maybeLineBreak();
cc.endBlock(context == Context.STATEMENT);
return;
} else {
// Continue with the only child.
nodeToProcess = firstAndOnlyChild;
}
}
}
if (nodeToProcess.getType() == Token.EMPTY) {
cc.endStatement(true);
} else {
add(nodeToProcess, context);
// VAR doesn't include ';' since it gets used in expressions - so any
// VAR in a statement context needs a call to endStatement() here.
if (nodeToProcess.getType() == Token.VAR) {
cc.endStatement();
}
}
}
/**
* Adds a node at the left-hand side of an expression. Unlike
* {@link #addExpr(Node,int)}, this preserves information about the context.
*
* The left side of an expression is special because in the JavaScript
* grammar, certain tokens may be parsed differently when they are at
* the beginning of a statement. For example, "{}" is parsed as a block,
* but "{'x': 'y'}" is parsed as an object literal.
*/
void addLeftExpr(Node n, int minPrecedence, Context context) {
addExpr(n, minPrecedence, context);
}
void addExpr(Node n, int minPrecedence) {
addExpr(n, minPrecedence, Context.OTHER);
}
private void addExpr(Node n, int minPrecedence, Context context) {
if ((NodeUtil.precedence(n.getType()) < minPrecedence) ||
((context == Context.IN_FOR_INIT_CLAUSE) &&
(n.getType() == Token.IN))
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>){
add("(");
add(n, clearContextForNoInOperator(context));
add(")");
} else {
add(n, context);
}
}
void addList(Node firstInList) {
addList(firstInList, true, Context.OTHER);
}
void addList(Node firstInList, boolean isArrayOrFunctionArgument) {
addList(firstInList, isArrayOrFunctionArgument, Context.OTHER);
}
void addList(Node firstInList, boolean isArrayOrFunctionArgument,
Context lhsContext) {
for (Node n = firstInList; n != null; n = n.getNext()) {
boolean isFirst = n == firstInList;
if (isFirst) {
addLeftExpr(n, isArrayOrFunctionArgument ? 1 : 0, lhsContext);
} else {
cc.listSeparator();
addExpr(n, isArrayOrFunctionArgument ? 1 : 0);
}
}
}
/**
* This function adds a comma-separated list as is specified by an ARRAYLIT
* node with the associated skipIndexes array. This is a space optimization
* since we avoid creating a whole Node object for each empty array literal
* slot.
* @param firstInList The first in the node list (chained through the next
* property).
* @param skipIndexes If not null, then the array of skipped entries in the
* array.
*/
void addList(Node firstInList, int[] skipIndexes) {
int nextSlot = 0;
int nextSkipSlot = 0;
for (Node n = firstInList; n != null; n = n.getNext()) {
while (skipIndexes != null && nextSkipSlot < skipIndexes.length) {
if (nextSlot == skipIndexes[nextSkipSlot]) {
cc.listSeparator();
nextSlot++;
nextSkipSlot++;
} else {
break;
}
}
if (n != firstInList) {
cc.listSeparator();
}
addExpr(n, 1);
nextSlot++;
}
}
void addCaseBody(Node caseBody) {
cc.beginCaseBody();
add(caseBody);
cc.endCaseBody();
}
void addAllSiblings(Node n) {
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
for (Node c = n; c != null; c = c.getNext()) {
add(c);
}
}
/** Outputs a js string, using the optimal (single/double) quote character */
static String jsString(String s, CharsetEncoder outputCharsetEncoder) {
int singleq = 0, doubleq = 0;
// could count the quotes and pick the optimal quote character
for (int i = 0; i < s.length(); i++) {
switch (s.charAt(i)) {
case '"': doubleq++; break;
case '\'': singleq++; break;
}
}
String doublequote, singlequote;
char quote;
if (singleq < doubleq) {
// more double quotes so escape the single quotes
quote = '\'';
doublequote = "\"";
singlequote = "\\\'";
} else {
// more single quotes so escape the doubles
quote = '\"';
doublequote = "\\\"";
singlequote = "\'";
}
return strEscape(s, quote, doublequote, singlequote, "\\\\",
outputCharsetEncoder);
}
/** Escapes regular expression */
static String regexpEscape(String s, CharsetEncoder outputCharsetEncoder) {
return strEscape(s, '/', "\"", "'", "\\", outputCharsetEncoder);
}
/**
* Escapes the given string to a double quoted (") JavaScript/JSON string
*/
static String escapeToDoubleQuotedJsString(String s) {
return strEscape(s, '"', "\\\"", "\'", "\\\\", null);
}
/* If the user doesn't want to specify an output charset encoder, assume
they want Latin/ASCII characters only.
*/
static String regexpEscape(String s) {
return regexpEscape(s, null);
}
/** Helper to escape javascript string as well as regular expression */
static String strEscape(String s, char quote,
String doublequoteEscape,
String singlequoteEscape,
String backslashEscape,
CharsetEncoder outputCharsetEncoder) {
StringBuilder sb = new StringBuilder();
sb.append(quote);
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '\n': sb.append("\\n"); break;
case
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> '\r': sb.append("\\r"); break;
case '\t': sb.append("\\t"); break;
case '\\': sb.append(backslashEscape); break;
case '\"': sb.append(doublequoteEscape); break;
case '\'': sb.append(singlequoteEscape); break;
case '>': // Break --> into --\> or ]]> into ]]\>
if (i >= 2 &&
((s.charAt(i - 1) == '-' && s.charAt(i - 2) == '-') ||
(s.charAt(i - 1) == ']' && s.charAt(i - 2) == ']'))) {
sb.append("\\>");
} else {
sb.append(c);
}
break;
case '<': // Break </script into <\/script
final String END_SCRIPT = "/script";
if (s.regionMatches(true, i + 1, END_SCRIPT, 0,
END_SCRIPT.length())) {
sb.append("<\\");
} else {
sb.append(c);
}
break;
default:
// If we're given an outputCharsetEncoder, then check if the
// character can be represented in this character set.
if (outputCharsetEncoder != null) {
if (outputCharsetEncoder.canEncode(c)) {
sb.append(c);
} else {
// Unicode-escape the character.
appendHexJavaScriptRepresentation(sb, c);
}
} else {
// No charsetEncoder provided - pass straight latin characters
// through, and escape the rest. Doing the explicit character
// check is measurably faster than using the CharsetEncoder.
if (c > 0x1f && c <= 0x7f) {
sb.append(c);
} else {
// Other characters can be misinterpreted by some js parsers,
// or perhaps mangled by proxies along the way,
// so we play it safe and unicode escape them.
appendHexJavaScriptRepresentation(sb, c);
}
}
}
}
sb.append(quote);
return sb.toString();
}
static String identifierEscape(String s) {
// First check if escaping is needed at all -- in most cases it isn't.
if (NodeUtil
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>.isLatin(s)) {
return s;
}
// Now going through the string to escape non-latin characters if needed.
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// Identifiers should always go to Latin1/ ASCII characters because
// different browser's rules for valid identifier characters are
// crazy.
if (c > 0x1F && c < 0x7F) {
sb.append(c);
} else {
appendHexJavaScriptRepresentation(sb, c);
}
}
return sb.toString();
}
/** Gets the number of children of this node that are non empty. */
private static int getNonEmptyChildCount(Node n) {
int i = 0;
for (Node c = n.getFirstChild(); c != null; c = c.getNext()) {
if (c.getType() != Token.EMPTY) {
i++;
}
}
return i;
}
/** Gets the first non-empty child of the given node. */
private static Node getFirstNonEmptyChild(Node n) {
for (Node c = n.getFirstChild(); c != null; c = c.getNext()) {
if (c.getType() != Token.EMPTY) {
return c;
}
}
return null;
}
// Information on the current context. Used for disambiguating special cases.
// For example, a "{" could indicate the start of an object literal or a
// block, depending on the current context.
enum Context {
STATEMENT,
BEFORE_DANGLING_ELSE, // a hack to resolve the else-clause ambiguity
START_OF_EXPR,
PRESERVE_BLOCK,
// Are we inside the init clause of a for loop? If so, the containing
// expression can't contain an in operator. Pass this context flag down
// until we reach expressions which no longer have the limitation.
IN_FOR_INIT_CLAUSE,
OTHER
}
private Context getContextForNonEmptyExpression(Context currentContext) {
return currentContext == Context.BEFORE_DANGLING_ELSE ?
Context.BEFORE_DANGLING_ELSE : Context.OTHER;
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>and so an assignment
// to the property of z would not violate any restrictions on it.
for (String property : typeB.properties.keySet()) {
if (!typeA.hasProperty(property)) {
return false;
}
JSType propA = typeA.getPropertyType(property);
JSType propB = typeB.getPropertyType(property);
if (!propA.isUnknownType() && !propB.isUnknownType()) {
if (typeA.isPropertyTypeDeclared(property)) {
if (!propA.equals(propB)) {
return false;
}
} else {
if (!propA.isSubtype(propB)) {
return false;
}
}
}
}
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{ ");
int i = 0;
for (String property : properties.keySet()) {
if (i > 0) {
sb.append(", ");
}
sb.append(property);
sb.append(" : ");
sb.append(properties.get(property).toString());
++i;
}
sb.append(" }");
return sb.toString();
}
@Override
JSType resolveInternal(ErrorReporter t, StaticScope<JSType> scope) {
for (Map.Entry<String, JSType> entry : properties.entrySet()) {
JSType type = entry.getValue();
JSType resolvedType = type.resolve(t, scope);
if (type != resolvedType) {
properties.put(entry.getKey(), resolvedType);
}
}
return super.resolveInternal(t, scope);
}
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> (it.hasNext()) {
JSType current = it.next();
if (!current.isUnknownType()) {
if (alternate.isSubtype(current)) {
// Alternate is unnecessary.
return this;
} else if (current.isSubtype(alternate)) {
// Alternate makes current obsolete
it.remove();
}
}
}
}
alternates.add(alternate);
result = null; // invalidate the memoized result
}
} else {
result = null;
}
return this;
}
/**
* Creates a union.
* @return A UnionType if it has two or more alternates, the
* only alternate if it has one and otherwise {@code NO_TYPE}.
*/
JSType build() {
if (result == null) {
if (isAllType) {
result = registry.getNativeType(ALL_TYPE);
} else if (isNativeUnknownType) {
if (areAllUnknownsChecked) {
result = registry.getNativeType(CHECKED_UNKNOWN_TYPE);
} else {
result = registry.getNativeType(UNKNOWN_TYPE);
}
} else {
Set<JSType> alternateSet = Sets.newUnmodifiableHashSet(alternates);
int size = alternateSet.size();
if (size > MAX_UNION_SIZE) {
result = registry.getNativeType(UNKNOWN_TYPE);
} else {
if (size > 1) {
result = new UnionType(registry, alternateSet);
} else if (size == 1) {
result = alternates.iterator().next();
} else {
result = registry.getNativeType(NO_TYPE);
}
}
}
}
return result;
}
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> the list of objects registered to receive
* notification of changes to a bounded property
* @see java.beans.PropertyChangeEvent
* @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
* @param l the listener
*/
public final void removePropertyChangeListener(PropertyChangeListener l)
{
if (sealed) onSealedMutation();
propertyListeners = Kit.removeListener(propertyListeners, l);
}
/**
* Notify any registered listeners that a bounded property has changed
* @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
* @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
* @see java.beans.PropertyChangeListener
* @see java.beans.PropertyChangeEvent
* @param property the bound property
* @param oldValue the old value
* @param newValue the new value
*/
final void firePropertyChange(String property, Object oldValue,
Object newValue)
{
Object listeners = propertyListeners;
if (listeners != null) {
firePropertyChangeImpl(listeners, property, oldValue, newValue);
}
}
private void firePropertyChangeImpl(Object listeners, String property,
Object oldValue, Object newValue)
{
for (int i = 0; ; ++i) {
Object l = Kit.getListener(listeners, i);
if (l == null)
break;
if (l instanceof PropertyChangeListener) {
PropertyChangeListener pcl = (PropertyChangeListener)l;
pcl.propertyChange(new PropertyChangeEvent(
this, property, oldValue, newValue));
}
}
}
/**
* Report a warning using the error reporter for the current thread.
*
* @param message the warning message to report
* @param sourceName a string describing the source, such as a filename
* @param lineno the starting line number
* @param lineSource the text of the line (may be null)
* @param lineOffset the offset into lineSource where problem was detected
* @see com.google.javascript.rhino.ErrorReporter
*/
public static void reportWarning(String message, String sourceName,
int lineno, String lineSource,
int lineOffset)
{
Context cx = Context.getContext();
cx.getErrorReporter().warning(message, sourceName, lineno,
lineSource, lineOffset);
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> associated with current Thread");
}
return cx;
}
final boolean isVersionECMA1()
{
return version == VERSION_DEFAULT || version >= VERSION_1_3;
}
static String getSourcePositionFromStack(int[] linep)
{
Context cx = getCurrentContext();
if (cx == null)
return null;
/**
* A bit of a hack, but the only way to get filename and line
* number from an enclosing frame.
*/
CharArrayWriter writer = new CharArrayWriter();
RuntimeException re = new RuntimeException();
re.printStackTrace(new PrintWriter(writer));
String s = writer.toString();
int open = -1;
int close = -1;
int colon = -1;
for (int i=0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == ':')
colon = i;
else if (c == '(')
open = i;
else if (c == ')')
close = i;
else if (c == '\n' && open != -1 && close != -1 && colon != -1 &&
open < colon && colon < close)
{
String fileStr = s.substring(open + 1, colon);
if (!fileStr.endsWith(".java")) {
String lineStr = s.substring(colon + 1, close);
try {
linep[0] = Integer.parseInt(lineStr);
if (linep[0] < 0) {
linep[0] = 0;
}
return fileStr;
}
catch (NumberFormatException e) {
// fall through
}
}
open = close = colon = -1;
}
}
return null;
}
public final boolean isGeneratingDebugChanged()
{
return generatingDebugChanged;
}
/**
* Add a name to the list of names forcing the creation of real
* activation objects for functions.
*
* @param name the name of the object to add to the list
*/
public void addActivationName(String name)
{
if (sealed) onSealedMutation();
if (activationNames == null)
activationNames = new Hashtable<Object, Object>(5);
activationNames.put(name, name);
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
/**
* Use closure's implementation.
* @return closure's function name for exporting properties.
*/
@Override
public String getExportPropertyFunction() {
return "goog.exportProperty";
}
/**
* Use closure's implementation.
* @return closure's function name for exporting symbols.
*/
@Override
public String getExportSymbolFunction() {
return "goog.exportSymbol";
}
@Override
public List<String> identifyTypeDeclarationCall(Node n) {
Node callName = n.getFirstChild();
if ("goog.addDependency".equals(callName.getQualifiedName()) &&
n.getChildCount() >= 3) {
Node typeArray = callName.getNext().getNext();
if (typeArray.getType() == Token.ARRAYLIT) {
List<String> typeNames = Lists.newArrayList();
for (Node name = typeArray.getFirstChild(); name != null;
name = name.getNext()) {
if (name.getType() == Token.STRING) {
typeNames.add(name.getString());
}
}
return typeNames;
}
}
return null;
}
@Override
public String identifyTypeDefAssign(Node n) {
Node firstChild = n.getFirstChild();
int type = n.getType();
if (type == Token.ASSIGN) {
if (TYPEDEF_NAME.equals(n.getLastChild().getQualifiedName())) {
return firstChild.getQualifiedName();
}
} else if (type == Token.VAR && firstChild.hasChildren()) {
if (TYPEDEF_NAME.equals(
firstChild.getFirstChild().getQualifiedName())) {
return firstChild.getString();
}
}
return null;
}
@Override
public String getAbstractMethodName() {
return "goog.abstractMethod";
}
@Override
public String getSingletonGetterClassName(Node callNode) {
Node callName = callNode.getFirstChild();
if (!"goog.addSingletonGetter".equals(callName.getQualifiedName()) ||
callName.getChildCount() != 2) {
return null;
}
Node classNode = callName.getNext();
if (!classNode.isQualifiedName()) {
return null;
}
return callName.getNext().getQualifiedName();
}
@Override
public void applySingletonGetter(
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> int charno) {
this(nodeType, children);
sourcePosition = mergeLineCharNo(lineno, charno);
}
public Node(int nodeType, Node[] children) {
this.type = nodeType;
parent = null;
if (children.length != 0) {
this.first = children[0];
this.last = children[children.length - 1];
for (int i = 1; i < children.length; i++) {
if (null != children[i - 1].next) {
// fail early on loops. implies same node in array twice
throw new IllegalArgumentException("duplicate child");
}
children[i - 1].next = children[i];
Preconditions.checkArgument(children[i - 1].parent == null);
children[i - 1].parent = this;
}
Preconditions.checkArgument(
children[children.length - 1].parent == null);
children[children.length - 1].parent = this;
if (null != this.last.next) {
// fail early on loops. implies same node in array twice
throw new IllegalArgumentException("duplicate child");
}
}
}
public static Node newNumber(double number) {
return new NumberNode(number);
}
public static Node newNumber(double number, int lineno, int charno) {
return new NumberNode(number, lineno, charno);
}
public static Node newString(String str) {
return new StringNode(Token.STRING, str);
}
public static Node newString(int type, String str) {
return new StringNode(type, str);
}
public static Node newString(String str, int lineno, int charno) {
return new StringNode(Token.STRING, str, lineno, charno);
}
public static Node newString(int type, String str, int lineno, int charno) {
return new StringNode(type, str, lineno, charno);
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public boolean hasChildren() {
return first != null;
}
public Node getFirstChild() {
return first;
}
public Node getLastChild
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>() {
return last;
}
public Node getNext() {
return next;
}
public Node getChildBefore(Node child) {
if (child == first)
return null;
Node n = first;
while (n.next != child) {
n = n.next;
if (n == null)
throw new RuntimeException("node is not a child");
}
return n;
}
public Node getChildAtIndex(int i) {
Node n = first;
while (i > 0) {
n = n.next;
i--;
}
return n;
}
public Node getLastSibling() {
Node n = this;
while (n.next != null) {
n = n.next;
}
return n;
}
public void addChildToFront(Node child) {
Preconditions.checkArgument(child.parent == null);
Preconditions.checkArgument(child.next == null);
child.parent = this;
child.next = first;
first = child;
if (last == null) {
last = child;
}
}
public void addChildToBack(Node child) {
Preconditions.checkArgument(child.parent == null);
Preconditions.checkArgument(child.next == null);
child.parent = this;
child.next = null;
if (last == null) {
first = last = child;
return;
}
last.next = child;
last = child;
}
public void addChildrenToFront(Node children) {
for (Node child = children; child != null; child = child.next) {
Preconditions.checkArgument(child.parent == null);
child.parent = this;
}
Node lastSib = children.getLastSibling();
lastSib.next = first;
first = children;
if (last == null) {
last = lastSib;
}
}
public void addChildrenToBack(Node children) {
for (Node child = children; child != null; child = child.next) {
// Hmmm... IRFactory doesn't remove before calling this.
Preconditions.checkArgument(child.parent == null);
child.parent = this;
}
if (last != null) {
last.next = children;
}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>(sof.getEncodedSourceEnd()
- sof.getEncodedSourceStart());
sb.append("] [base line: ");
sb.append(sof.getBaseLineno());
sb.append("] [end line: ");
sb.append(sof.getEndLineno());
sb.append(']');
}
} else if (type == Token.NUMBER) {
sb.append(' ');
sb.append(getDouble());
}
if (printSource) {
int lineno = getLineno();
if (lineno != -1) {
sb.append(' ');
sb.append(lineno);
}
}
if (printAnnotations) {
int[] keys = getSortedPropTypes();
for (int i = 0; i < keys.length; i++) {
int type = keys[i];
PropListItem x = lookupProperty(type);
sb.append(" [");
sb.append(propToString(type));
sb.append(": ");
String value;
switch (type) {
case TARGETBLOCK_PROP : // can't add this as it recurses
value = "target block property";
break;
case LOCAL_BLOCK_PROP : // can't add this as it is dull
value = "last local block";
break;
case ISNUMBER_PROP:
switch (x.intValue) {
case BOTH:
value = "both";
break;
case RIGHT:
value = "right";
break;
case LEFT:
value = "left";
break;
default:
throw Kit.codeBug();
}
break;
case SPECIALCALL_PROP:
switch (x.intValue) {
case SPECIALCALL_EVAL:
value = "eval";
break;
case SPECIALCALL_WITH:
value = "with";
break;
default:
// NON_SPECIALCALL should not be stored
throw Kit.codeBug();
}
break;
default :
Object obj = x.objectValue;
if (obj != null) {
value = obj.toString();
} else {
value = String.valueOf(x.intValue);
}
break;
}
sb.append(value);
sb.append(']');
}
}
if (printType) {
if (jsType != null) {
String jsTypeString =
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> jsType.toString();
if (jsTypeString != null) {
sb.append(" : ");
sb.append(jsTypeString);
}
}
}
}
}
public String toStringTree() {
return toStringTreeImpl();
}
private String toStringTreeImpl() {
try {
StringBuffer s = new StringBuffer();
appendStringTree(s);
return s.toString();
} catch (IOException e) {
throw new RuntimeException("Should not happen\n" + e);
}
}
public void appendStringTree(Appendable appendable) throws IOException {
toStringTreeHelper(this, 0, appendable);
}
private static void toStringTreeHelper(Node n, int level, Appendable sb)
throws IOException
{
if (Token.printTrees) {
for (int i = 0; i != level; ++i) {
sb.append(" ");
}
sb.append(n.toString());
sb.append('\n');
for (Node cursor = n.getFirstChild(); cursor != null;
cursor = cursor.getNext())
{
toStringTreeHelper(cursor, level + 1, sb);
}
}
}
int type; // type of the node; Token.NAME for example
Node next; // next sibling
private Node first; // first element of a linked list of children
private Node last; // last element of a linked list of children
/**
* Linked list of properties. Since vast majority of nodes would have
* no more then 2 properties, linked list saves memory and provides
* fast lookup. If this does not holds, propListHead can be replaced
* by UintMap.
*/
private PropListItem propListHead;
/**
* COLUMN_BITS represents how many of the lower-order bits of
* sourcePosition are reserved for storing the column number.
* Bits above these store the line number.
* This gives us decent position information for everything except
* files already passed through a minimizer, where lines might
* be longer than 4096 characters.
*/
public static final int COLUMN_BITS = 12;
/**
* MAX_COLUMN_NUMBER represents the maximum column number that can
* be represented. JSCompiler's modifications to Rhino cause all
* tokens located beyond the maximum column to
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>
case Token.CONTINUE: return "continue";
case Token.VAR: return "var";
case Token.WITH: return "with";
case Token.CATCH: return "catch";
case Token.FINALLY: return "finally";
case Token.RESERVED: return "reserved";
case Token.NOT: return "not";
case Token.VOID: return "void";
case Token.BLOCK: return "block";
case Token.ARRAYLIT: return "arraylit";
case Token.OBJECTLIT: return "objectlit";
case Token.LABEL: return "label";
case Token.TARGET: return "target";
case Token.LOOP: return "loop";
case Token.EXPR_VOID: return "expr_void";
case Token.EXPR_RESULT: return "expr_result";
case Token.JSR: return "jsr";
case Token.SCRIPT: return "script";
case Token.EMPTY: return "empty";
case Token.GET_REF: return "get_ref";
case Token.REF_SPECIAL: return "ref_special";
}
return "<unknown="+token+">";
}
/** Returns true if this node is equivalent semantically to another */
public boolean isEquivalentTo(Node node) {
if (type == Token.ARRAYLIT) {
try {
int[] indices1 = (int[])getProp(Node.SKIP_INDEXES_PROP);
int[] indices2 = (int[])node.getProp(Node.SKIP_INDEXES_PROP);
if (indices1 == null) {
if (indices2 != null)
return false;
} else if (indices2 == null) {
return false;
} else if (indices1.length != indices2.length) {
return false;
} else {
for (int i = 0; i < indices1.length; i++) {
if (indices1[i] != indices2[i])
return false;
}
}
} catch (Exception e) {
return false;
}
} else if (type == Token.INC ||
type == Token.DEC) {
int post1 = this.getIntProp(INCRDECR_PROP, 0);
int post2 =
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>.VOID_TYPE));
register(getNativeType(JSTypeNative.VOID_TYPE), "Undefined");
register(getNativeType(JSTypeNative.VOID_TYPE), "void");
register(getNativeType(JSTypeNative.FUNCTION_INSTANCE_TYPE), "Function");
}
private void register(JSType type) {
register(type, type.toString());
}
private void register(JSType type, String name) {
namesToTypes.put(name, type);
// Add all the namespaces in which this name lives.
while (name.indexOf('.') > 0) {
name = name.substring(0, name.lastIndexOf('.'));
namespaces.add(name);
}
}
private void registerNativeType(JSTypeNative typeId, JSType type) {
nativeTypes[typeId.ordinal()] = type;
}
/**
* Tells the type system that {@code owner} may have a property named
* {@code propertyName}. This allows the registry to keep track of what
* types a property is defined upon.
*
* This is NOT the same as saying that {@code owner} must have a property
* named type. ObjectType#hasProperty attempts to minimize false positives
* ("if we're not sure, then don't type check this property"). The type
* registry, on the other hand, should attempt to minimize false negatives
* ("if this property is assigned anywhere in the program, it must
* show up in the type registry").
*/
public void registerPropertyOnType(String propertyName, ObjectType owner) {
Set<ObjectType> typeSet = typesIndexedByProperty.get(propertyName);
if (typeSet == null) {
typesIndexedByProperty.put(propertyName, typeSet = Sets.newHashSet());
}
greatestSubtypeByProperty.remove(propertyName);
typeSet.add(owner);
}
/**
* Gets the greatest subtype of the {@code type} that has a property
* {@code propertyName} defined on it.
*/
public JSType getGreatestSubtypeWithProperty(
JSType type, String propertyName) {
if (greatestSubtypeByProperty.containsKey(propertyName)) {
return greatestSubtypeByProperty.get(propertyName)
.getGreatestSubtype(type);
}
if (typesIndexedByProperty.containsKey(propertyName)) {
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>ToImplementors.put(interfaceInstance.getReferenceName(), type);
}
/**
* Returns a collection of types that directly implement {@code
* interfaceInstance}. Subtypes of implementing types are not guaranteed to
* be returned. {@code interfaceInstance} must be an ObjectType for the
* instance of the interface.
*/
public Collection<FunctionType> getDirectImplementors(
ObjectType interfaceInstance) {
return interfaceToImplementors.get(interfaceInstance.getReferenceName());
}
/**
* Records declared type names. Given the limited scopes of JavaScript, all
* named types are dumped in a common global scope. We may need to revise this
* assumption in the future.
*
* @param name The name of the type to be recorded.
* @param t The actual type being associated with the name.
* @return True if this name is not already defined, false otherwise.
*/
public boolean declareType(String name, JSType t) {
if (namesToTypes.containsKey(name)) {
return false;
}
register(t, name);
return true;
}
/**
* Records a forward-declared type name. We will not emit errors if this
* type name never resolves to anything.
*/
public void forwardDeclareType(String name) {
forwardDeclaredTypes.add(name);
}
/**
* Whether this is a forward-declared type name.
*/
public boolean isForwardDeclaredType(String name) {
return forwardDeclaredTypes.contains(name);
}
/** Determines whether the given JS package exists. */
public boolean hasNamespace(String name) {
return namespaces.contains(name);
}
/**
* Looks up a type by name.
*
* @param jsTypeName The name string.
* @return the corresponding JSType object or {@code null} it cannot be found
*/
public JSType getType(String jsTypeName) {
// TODO(user): Push every local type name out of namesToTypes so that
// NamedType#resolve is correct.
if (jsTypeName.equals(templateTypeName)) {
return templateType;
}
return namesToTypes.get(jsTypeName);
}
public JSType getNativeType(JSTypeNative typeId) {
return nativeTypes[typeId.ordinal()];
}
public ObjectType getNative
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> The last element of this array
* is considered a variable length argument.
* @return a tree hierarchy representing a typed argument list.
*/
public Node createParametersWithVarArgs(JSType... parameterTypes) {
return createParameters(true, parameterTypes);
}
/**
* Creates a tree hierarchy representing a typed parameter list in which
* every parameter is optional.
*/
public Node createOptionalParameters(JSType... parameterTypes) {
FunctionParamBuilder builder = new FunctionParamBuilder(this);
builder.addOptionalParams(parameterTypes);
return builder.build();
}
/**
* Creates a tree hierarchy representing a typed argument list.
*
* @param lastVarArgs whether the last type should considered as a variable
* length argument.
* @param parameterTypes the parameter types. The last element of this array
* is considered a variable length argument is {@code lastVarArgs} is
* {@code true}.
* @return a tree hierarchy representing a typed argument list
*/
private Node createParameters(boolean lastVarArgs, JSType... parameterTypes) {
FunctionParamBuilder builder = new FunctionParamBuilder(this);
int max = parameterTypes.length - 1;
for (int i = 0; i <= max; i++) {
if (lastVarArgs && i == max) {
builder.addVarArgs(parameterTypes[i]);
} else {
builder.addRequiredParams(parameterTypes[i]);
}
}
return builder.build();
}
/**
* Creates a function type.
* @param returnType the function's return type
* @param lastVarArgs whether the last parameter type should be considered as
* an extensible var_args parameter
* @param parameterTypes the parameters' types
*/
public FunctionType createFunctionType(JSType returnType,
boolean lastVarArgs, JSType... parameterTypes) {
if (lastVarArgs) {
return createFunctionTypeWithVarArgs(returnType, parameterTypes);
} else {
return createFunctionType(returnType, parameterTypes);
}
}
/**
* Creates a new function type based on an existing function type but
* with a new return type.
* @param existingFunctionType the existing function type.
* @param returnType the new return type.
*/
public FunctionType createFunctionTypeWithNewReturnType(
Function
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> true, false);
}
/**
* Creates an interface function type.
* @param name the function's name
* @param source the node defining this function. Its type
* ({@link Node#getType()}) must be {@link Token#FUNCTION}.
*/
public FunctionType createInterfaceType(String name, Node source) {
return new FunctionType(this, name, source);
}
/**
* Creates a parameterized type.
*/
public ParameterizedType createParameterizedType(
ObjectType objectType, JSType parameterType) {
return new ParameterizedType(this, objectType, parameterType);
}
/**
* Identifies the name of an enum before we actually declare it.
*/
public void identifyEnumName(String name) {
enumTypeNames.add(name);
}
/**
* Creates a RecordType from the nodes representing said record type.
* @param n The node with type info.
* @param sourceName The source file name.
* @param scope A scope for doing type name lookups.
*/
public JSType createRecordTypeFromNodes(Node n, String sourceName,
StaticScope<JSType> scope) {
RecordTypeBuilder builder = new RecordTypeBuilder(this);
// For each of the fields in the record type.
for (Node fieldTypeNode = n.getFirstChild();
fieldTypeNode != null;
fieldTypeNode = fieldTypeNode.getNext()) {
// Get the property's name.
Node fieldNameNode = fieldTypeNode;
boolean hasType = false;
if (fieldTypeNode.getType() == Token.COLON) {
fieldNameNode = fieldTypeNode.getFirstChild();
hasType = true;
}
String fieldName = fieldNameNode.getString();
// TODO(user): Move this into the lexer/parser.
// Remove the string literal characters around a field name,
// if any.
if (fieldName.startsWith("'") || fieldName.startsWith("\"")) {
fieldName = fieldName.substring(1, fieldName.length() - 1);
}
// Get the property's type.
JSType fieldType = null;
if (hasType) {
// We have a declared type.
fieldType = createFromTypeNodes(
fieldTypeNode.getLastChild(), sourceName, scope);
} else {
// Otherwise, the type is UNKNOWN.
fieldType =
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> code will only run checks and not optimizations.
*/
abstract protected List<PassFactory> getChecks();
/**
* Gets the optimization passes to run.
*
* Optimization passes revolve around producing smaller and faster code.
* They should always run after checking passes.
*/
abstract protected List<PassFactory> getOptimizations();
/**
* Gets a graph of the passes run. For debugging.
*/
GraphvizGraph getPassGraph() {
LinkedDirectedGraph<String, String> graph = LinkedDirectedGraph.create();
Iterable<PassFactory> allPasses =
Iterables.concat(getChecks(), getOptimizations());
String lastPass = null;
String loopStart = null;
for (PassFactory pass : allPasses) {
String passName = pass.getName();
int i = 1;
while (graph.hasNode(passName)) {
passName = pass.getName() + (i++);
}
graph.createNode(passName);
if (loopStart == null && !pass.isOneTimePass()) {
loopStart = passName;
} else if (loopStart != null && pass.isOneTimePass()) {
graph.connect(lastPass, "loop", loopStart);
loopStart = null;
}
if (lastPass != null) {
graph.connect(lastPass, "", passName);
}
lastPass = passName;
}
return graph;
}
/**
* Create a type inference pass.
*/
final TypeInferencePass makeTypeInference(AbstractCompiler compiler) {
return new TypeInferencePass(
compiler, compiler.getReverseAbstractInterpreter(),
topScope, typedScopeCreator);
}
/**
* Create a type-checking pass.
*/
final TypeCheck makeTypeCheck(AbstractCompiler compiler) {
return new TypeCheck(
compiler,
compiler.getReverseAbstractInterpreter(),
compiler.getTypeRegistry(),
topScope,
typedScopeCreator,
options.reportMissingOverride,
options.reportUnknownTypes)
.reportMissingProperties(options.enables(
DiagnosticGroup.forType(TypeCheck.INEXISTENT_PROPERTY)));
}
final static void addPassFactoryBefore(
List<PassFactory> factoryList, PassFactory factory, String passName) {
for (int i = 0; i
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> < factoryList.size(); i++) {
if (factoryList.get(i).getName().equals(passName)) {
factoryList.add(i, factory);
return;
}
}
throw new IllegalArgumentException(
"No factory named '" + passName + "' in the factory list");
}
/**
* Find the first pass provider that does not have a delegate.
*/
final PassConfig getBasePassConfig() {
PassConfig current = this;
while (current instanceof PassConfigDelegate) {
current = ((PassConfigDelegate) current).delegate;
}
return current;
}
/**
* Get intermediate state for a running pass config, so it can
* be paused and started again later.
*/
abstract State getIntermediateState();
/**
* Set the intermediate state for a pass config, to restart
* a compilation process that had been previously paused.
*/
abstract void setIntermediateState(State state);
/**
* An implementation of PassConfig that just proxies all its method calls
* into an inner class.
*/
static class PassConfigDelegate extends PassConfig {
private final PassConfig delegate;
PassConfigDelegate(PassConfig delegate) {
super(delegate.options);
this.delegate = delegate;
}
@Override protected List<PassFactory> getChecks() {
return delegate.getChecks();
}
@Override protected List<PassFactory> getOptimizations() {
return delegate.getOptimizations();
}
@Override ScopeCreator getScopeCreator() {
return delegate.getScopeCreator();
}
@Override Scope getTopScope() {
return delegate.getTopScope();
}
@Override State getIntermediateState() {
return delegate.getIntermediateState();
}
@Override void setIntermediateState(State state) {
delegate.setIntermediateState(state);
}
}
/**
* Intermediate state for a running pass configuration.
*/
static class State implements Serializable {
private static final long serialVersionUID = 1L;
final Map<String, Integer> cssNames;
final Set<String> exportedNames;
final CrossModuleMethodMotion.IdGenerator crossModuleIdGenerator;
final VariableMap variableMap;
final VariableMap propertyMap;
final VariableMap anonymousFunctionNameMap;
final FunctionNames functionNames;
State(Map<String, Integer> cssNames,
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS>.kind = Kind.INTERFACE;
this.typeOfThis = new InstanceObjectType(registry, this);
}
@Override
public boolean isInstanceType() {
// The universal constructor is its own instance, bizarrely.
return equals(registry.getNativeType(U2U_CONSTRUCTOR_TYPE));
}
@Override
public boolean isConstructor() {
return kind == Kind.CONSTRUCTOR;
}
@Override
public boolean isInterface() {
return kind == Kind.INTERFACE;
}
@Override
public boolean isOrdinaryFunction() {
return kind == Kind.ORDINARY;
}
@Override
public boolean isFunctionType() {
return true;
}
@Override
public boolean canBeCalled() {
return true;
}
public Iterable<Node> getParameters() {
Node n = getParametersNode();
if (n != null) {
return n.children();
} else {
return Collections.emptySet();
}
}
/** Gets an LP node that contains all params. May be null. */
public Node getParametersNode() {
return call == null ? null : call.parameters;
}
/** Gets the minimum number of arguments that this function requires. */
public int getMinArguments() {
// NOTE(nicksantos): There are some native functions that have optional
// parameters before required parameters. This algorithm finds the position
// of the last required parameter.
int i = 0;
int min = 0;
for (Node n : getParameters()) {
i++;
if (!n.isOptionalArg() && !n.isVarArgs()) {
min = i;
}
}
return min;
}
/**
* Gets the maximum number of arguments that this function requires,
* or Integer.MAX_VALUE if this is a variable argument function.
*/
public int getMaxArguments() {
Node params = getParametersNode();
if (params != null) {
Node lastParam = params.getLastChild();
if (lastParam == null || !lastParam.isVarArgs()) {
return params.getChildCount();
}
}
return Integer.MAX_VALUE;
}
public JSType getReturnType() {
return call == null ? null : call.returnType;
}
/**
* Gets the {@code prototype}
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> property of this function type. This is
* equivalent to {@code (ObjectType) getPropertyType("prototype")}.
*/
public FunctionPrototypeType getPrototype() {
// lazy initialization of the prototype field
if (prototype == null) {
setPrototype(new FunctionPrototypeType(registry, this, null));
}
return prototype;
}
/**
* Sets the prototype, creating the prototype object from the given
* base type.
* @param baseType The base type.
*/
public void setPrototypeBasedOn(ObjectType baseType) {
if (prototype == null) {
setPrototype(
new FunctionPrototypeType(
registry, this, baseType, isNativeObjectType()));
} else {
prototype.setImplicitPrototype(baseType);
}
}
/**
* Sets the prototype.
* @param prototype the prototype. If this value is {@code null} it will
* silently be discarded.
*/
public boolean setPrototype(FunctionPrototypeType prototype) {
if (prototype == null) {
return false;
}
// getInstanceType fails if the function is not a constructor
if (isConstructor() && prototype == getInstanceType()) {
return false;
}
this.prototype = prototype;
if (isConstructor() || isInterface()) {
FunctionType superClass = getSuperClassConstructor();
if (superClass != null) {
superClass.addSubType(this);
}
}
return true;
}
/**
* Returns all interfaces implemented by a class or its superclass and any
* superclasses for any of those interfaces. If this is called before all
* types are resolved, it may return an incomplete set.
*/
public Iterable<ObjectType> getAllImplementedInterfaces() {
Set<ObjectType> interfaces = Sets.newHashSet();
for (ObjectType type : getImplementedInterfaces()) {
addRelatedInterfaces(type, interfaces);
}
return interfaces;
}
private void addRelatedInterfaces(ObjectType instance, Set<ObjectType> set) {
FunctionType constructor = instance.getConstructor();
if (constructor != null) {
if (!constructor.isInterface()) {
return;
}
set.add(instance);
if (constructor.getSuperClassConstructor() != null) {
addRelatedInterfaces(
constructor.getSuperClassConstructor().getInstanceType(), set);
}
}
}
/** Returns interfaces
Closure, 140
<FILEB>
<CHANGES>
fillEmptyModules(modules);
<CHANGEE>
<CHANGES>
private void fillEmptyModules(JSModule[] modules) {
for (int i = 1; i < modules.length; i ++) {
JSModule module = modules[i];
if (module.getInputs().isEmpty()) {
module.add(JSSourceFile.fromCode("[" + module.getName() + "]", ""));
}
}
}
<CHANGEE>
<CHANGES>
<CHANGEE>
<FILEE>
<FILEB>
this.externs = makeCompilerInput(externs, true);
this.modules = null;
this.moduleGraph = null;
this.inputs = makeCompilerInput(inputs, false);
initBasedOnOptions();
initInputsByNameMap();
}
static final DiagnosticType MODULE_DEPENDENCY_ERROR =
DiagnosticType.error("JSC_MODULE_DEPENDENCY_ERROR",
"Bad dependency: {0} -> {1}. "
+ "Modules must be listed in dependency order.");
/**
* Initializes the instance state needed for a compile job.
*/
public void init(JSSourceFile[] externs, JSModule[] modules,
CompilerOptions options) {
initOptions(options);
checkFirstModule(modules);
<CHANGES>
<CHANGEE>
this.externs = makeCompilerInput(externs, true);
this.modules = modules;
// Generate the module graph, and report any errors in the module
// specification as errors.
try {
this.moduleGraph = new JSModuleGraph(modules);
} catch (JSModuleGraph.ModuleDependenceException e) {
// problems with the module format. Report as an error. The
// message gives all details.
report(JSError.make(MODULE_DEPENDENCY_ERROR,
e.getModule().getName(), e.getDependentModule().getName()));
return;
DiagnosticType.error("JSC_EMPTY_ROOT_MODULE_ERROR",
"Root module '{0}' must contain at least one source code input");
/**
* Verifies that at least one module has been provided and that the first one
* has at least one source code input.
*/
private void checkFirstModule(JSModule[] modules) {
if (modules.length == 0) {
report(JSError.make(EMPTY_MODULE_LIST_ERROR));
} else if (modules[0].getInputs().isEmpty()) {
report(JSError.make(EMPTY_ROOT_MODULE_ERROR,
modules[0].getName()));
}
}
/**
* Fill any empty modules with a place holder file. It makes any cross module
* motion easier.
*/
<CHANGES>
<CHANGEE>
static final DiagnosticType DUPLICATE_INPUT_IN_MODULES =
DiagnosticType.error("JSC_DUPLICATE_INPUT_IN_MODULES_ERROR",
"Two modules cannot<SCANS> * Gets the source node or null if this is an unknown function.
*/
public Node getSource() {
return source;
}
/**
* Sets the source node.
*/
public void setSource(Node source) {
this.source = source;
}
/** Adds a type to the list of subtypes for this type. */
private void addSubType(FunctionType subType) {
if (subTypes == null) {
subTypes = Lists.newArrayList();
}
subTypes.add(subType);
}
/**
* Returns a list of types that are subtypes of this type. This is only valid
* for constructor functions, and may be null. This allows a downward
* traversal of the subtype graph.
*/
public List<FunctionType> getSubTypes() {
return subTypes;
}
@Override
public boolean hasCachedValues() {
return prototype != null || super.hasCachedValues();
}
/**
* Gets the template type name.
*/
public String getTemplateTypeName() {
return templateTypeName;
}
@Override
JSType resolveInternal(ErrorReporter t, StaticScope<JSType> scope) {
call = (ArrowType) safeResolve(call, t, scope);
prototype = (FunctionPrototypeType) safeResolve(prototype, t, scope);
typeOfThis = (ObjectType) safeResolve(typeOfThis, t, scope);
boolean changed = false;
ImmutableList.Builder<ObjectType> resolvedInterfaces =
ImmutableList.builder();
for (ObjectType iface : implementedInterfaces) {
ObjectType resolvedIface = (ObjectType) iface.resolve(t, scope);
resolvedInterfaces.add(resolvedIface);
changed |= (resolvedIface != iface);
}
if (changed) {
implementedInterfaces = resolvedInterfaces.build();
}
if (subTypes != null) {
for (int i = 0; i < subTypes.size(); i++) {
subTypes.set(i, (FunctionType) subTypes.get(i).resolve(t, scope));
}
}
return super.resolveInternal(t, scope);
}
}